Notifications
Clear all

[Closed] getSaveFileName and Win 7

I wrote a tool that will let the user select a save file using getSaveFileName for a export process.
Once it’s selected, I check if the file is readonly, and if ‘True’ then use a dos command to ‘check out’ the file from file storage application.

The issue is this process doesn’t appear to work on win 7 machines because it stops you from selecting a ‘readonly’ file in the dialog. Essentially stopping right there. I can’t get past this point in order to process and check out the file.

Any ideas?

7 Replies

Sounds like a user account control (UAC) issue, have you tried turning it off?

Sorry for the delay in response,
Yes, I’ve tested it with UAC turned off and the issue still exists.

Have you tried different paths for the file? For example, one that it’s not on the c:\users\Administrator and try it on a c: est.tmp file?

If you can, please post a snippet of your code.

Correct, the current paths are not in any of the user directories.

sFileName = getSaveFileName filename:sExportName
types:“SMDExporter(.smd)|.smd”

I don’t see any options for this command that are related to readonly or over-writing. Your basically just selecting a filename. in XP, it doesn’t care if your selecting a file marked as readonly or not. This doesn’t appear to be the case with Win7. It will NOT allow you to select a file marked as readonly. So you have to cancel which will return undefined.

Well I was digging a .net solution but it has the same problem, but while coding I had an idea, why not use the openfiledialog and if the file exists, it checks for the read-only flag, and if it’s true, remove it and overwrite the file. If the file doesnt exist, then just create it. Made any sense?

With getSave you can select any file including one that doesn’t exist.

With getOpen you can only select files that exist, the dialog will give you the same issues if you try to select a file that doesn’t already exist. Dialog will hang there until you select a valid choice or cancel.

Since I Don’t know what the user is going to select ( new or existing ) I can’t squeak by using getOpen.

It’s not pretty, but a more prettier solution involved messing deeply with the savefiledialog messages and that’s wayyy beyond my knowledge, either way, it was a cool challenge, I never did anything with dialogops and uiaccessor

Anyway, as I’ve said it’s not pretty because when the error dialog appears we can see it by a split second being closed by the uiaccessor, but I guess it’s effective anyway. Another problem would be localization issues, so any non-english 3dsmax wouldnt work with this.

Hope this helps anyway:

(
	clearlistener()
	DialogMonitorOPS.unRegisterNotification id:#eyeInTheSky
	frmSaveFileDialog = dotNetObject "System.Windows.Forms.SaveFileDialog"
	
	fn checkfilesave ipath ifile =
	(
		fpath = ipath + ifile
		result = getFileAttribute fpath #readonly
	)
	
	fn dmnotification = 
	(
		 WindowHandle = DialogMonitorOPS.GetWindowHandle()
		-- Window info, for debbuging only
		/* format "Dialog Window Handle: %
" WindowHandle
		 format "Dialog Name: %
" (UIAccessor.GetWindowText WindowHandle)
		 format "Window Class Name: %
" (UIAccessor.GetWindowClassName WindowHandle)
		 format "Window Resource ID: %
" (UIAccessor.GetWindowResourceID WindowHandle)
		 format "Is Window: %
" (UIAccessor.isWindow WindowHandle)
		 format "Window DLL Filename: %
" (UIAccessor.GetWindowDllFileName WindowHandle)
		 format "Window DLL Description: %
" (UIAccessor.GetWindowDllDescription WindowHandle)*/

		if (UIAccessor.GetWindowText WindowHandle) == "Confirm Save As" then -- file overwrite info dialog
		(

			parent = UIAccessor.GetParentWindow WindowHandle
			controls = windows.getChildrenHWND parent

			fpath = ""
			ffile = ""			
			for i in controls do
			(
				case i[4] of
				(
					"ToolbarWindow32":if i[5] != "" then fpath = substitutestring i[5] "Address: " ""
					"Edit":ffile += i[5]
				)
			)
			fpath += @"\"
			rrfile = checkfilesave fpath ffile
			if rrfile == true then
			(
				ipath = fpath + ffile
				setFileAttribute ipath #readonly false
				/* File exists and is read-only - do your stuff here */
				setFileAttribute ipath #readonly true
			)
			else 
			(
				/* file exists and it's not read-only - do your stuff here */
			)
		)
		
		if (UIAccessor.GetWindowText WindowHandle) == "Save As" then -- main dialog and error dialog - they have the same caption
		(
				controls = windows.getChildrenHWND WindowHandle
				nbuttons = for  i in controls where i[4] == "Button" collect i
				if nbuttons.count == 1 then -- file save error dialog it shows even though we did set the file attribute not to be read only, so we just want to close this
				(
					UIAccessor.CloseDialog  WindowHandle
					parent = UIAccessor.GetParentWindow WindowHandle -- now that we're done, we can also close the main dialog
					UIAccessor.CloseDialog  parent
					DialogMonitorOPS.UnRegisterNotification id:#eyeInTheSky					
				)
		)				
		--format "=====================
"
		true
	)

	DialogMonitorOPS.RegisterNotification dmnotification id:#eyeInTheSky

	DialogMonitorOPS.Enabled = true
	DialogMonitorOPS.ShowNotification()
	
	
	frmSaveFileDialog.Filter = "SMDExporter (*.smd)|*.smd"
	
	dlgResult = dotNetClass "System.Windows.Forms.DialogResult"
	if frmSaveFileDialog.ShowDialog() == dlgResult.OK then
	(
		/*  file doesn't exist - do your stuff here */
		print frmSaveFileDialog.Filename
	)
		
)