how to bring the choose.file() dialog to the foreground - user-interface

I'm using the function choose.dir() in a script that is run with rscript.exe under Windows XP. The problem is that the directory choosing dialog does not pop up as a top-level window. How can I bring the dialogue to the foreground?
In the meantime, I solved my problem by using visual basic script. Of course, this only works with windows:
tf <- tempfile(fileext = '.vbs')
cat('Set folder = CreateObject("Shell.Application") _
.BrowseForFolder(0, "Please choose a folder" _
, &H0001, 17)
Wscript.Echo folder.Self.Path
', file = tf)
tail(shell(paste('Cscript', tf), intern = T), 1)

After searching the rhelp archives it appears the answer is that you can't use choose.dir and file.choose in a non-interactive session. You might be able to do something similar, since list.files, file.info, file.access and files can be used to gather information, you can display this by writing to a graphics device and executing a system() call to get it displayed, and readLines can be used to get user input.

Related

SAS Enterprise Guide with VBScript. Looping through SAS programs get stuck

I'm facing a random problem. When executing SAS programs with VBScript and the SASEGObjectModel.Application.7.1, looping through CodeCollection get stuck sometimes, even if the program execution was succeeded (the final data bases are correctly created in our server). The script simple doesn't go to the next program of CodeCollection (the prompt executing the script still open... ad infinitum). The SAS program It happens is random, also the frequency. I'm going with something like this:
Dim oSasApp
Set oSasApp = CreateObject("SASEGObjectModel.Application.7.1")
oSasApp.SetActiveProfile("some-profile")
Dim oSasProj
Set oSasProj = oSasApp.Open("some-project.egp", "")
Dim oProgramList
Set oProgramList = oSasProj.CodeCollection
Dim programOrder
Set programOrder = ...here I assign the SAS programs order array reading from a .txt...
For Each program in programOrder
For Each sasProgram in oProgramList
If sasProgram.Name = program Then
sasProgram.Run
sasProgram.Log.SaveAs "some-folder/" & sasProgram.Name & ".txt"
End If
Next
Next
oSasProj.Close
oSasApp.Quit
The problem is not the Log saving, as the log txt file of the stucked program is also correctly created.
Any idea? Maybe problems in our SAS server? Should I declare some kind of options?
SAS Guide version: 7.15
Windows: 10
Tks
So... for people facing the same problem. As I commented above, if I press enter on prompt the script flows again. So it is waiting for my input, for reasons I can't tell. I did 2 things to get around it. Not sure if all of them are necessary or if only one solves it, but here it goes:
First, by VBScript I turned off a list of generations and I applied a delay after the SAS program runs:
For Each program in programOrder
For Each sasProgram i oProgramList
If sasProgram.Name = program Then
sasProgram.GenSasReport = False
sasProgram.GenHTML = False
sasProgram.GenListing = False
sasProgram.GenPDF = False
sasProgram.GenRTF = False
sasProgram.Run
WScript.Sleep(2000)
sasProgram.Log.SaveAs "some-folder/" & sasProgram.Name & ".txt"
End If
Next
Next
Them, in my batch file, wich I use to call the VBScript with the "cscript" command, I set it to apply "y" to every single message the VBScript could ask:
cd ./script-folder
echo y | cscript script-file-name.vbs
And that is it.

Can I get the return value of Shell.Application's ShellExecute?

I'm using VBScript to create a UAC prompt for a batch file. I don't know how to get the return value of the UAC prompt. For example if I try to UAC a file that doesn't exist I should get an error, right?
For example:
Dim rc
Set UAC = CreateObject("Shell.Application")
rc = UAC.ShellExecute("thisdoesntexist.exe", "", "", "runas", 1)
WScript.Echo rc
rc doesn't contain a code. Also, is there any way I can get the error code of whatever I'm executing? Is ShellExecute asynchronous in VBScript?
IShellDispatch2.ShellExecute method
Performs a specified operation on a specified file.
Syntax
IShellDispatch2.ShellExecute(sFile [, vArguments] [, vDirectory] [,
vOperation] [, vShow]) Parameters
sFile Required. String that contains the name of the file on which
ShellExecute will perform the action specified by vOperation.
vArguments Optional. Variant that contains the parameter values for
the operation.
vDirectory Optional. Variant that contains the fully qualified path of
the directory that contains the file specified by sFile. If this
parameter is not specified, the current working directory is used.
vOperation Optional. Variant that specifies the operation to be
performed. It should be set to one of the verb strings that is
supported by the file. For a discussion of verbs, see the Remarks
section. If this parameter is not specified, the default operation is
performed.
vShow Optional. Variant that recommends how the window that belongs to
the application that performs the operation should be displayed
initially. The application can ignore this recommendation. vShow can
take one of the following values. If this parameter is not specified,
the application uses its default value.0
Open the application with a hidden window.
1 Open the application with a normal window. If the window is
minimized or maximized, the system restores it to its original size
and position.
2 Open the application with a minimized window.
3 Open the application with a maximized window.
4 Open the application with its window at its most recent size and
position. The active window remains active.
5 Open the application with its window at its current size and
position.
7 Open the application with a minimized window. The active window
remains active.
10 Open the application with its window in the default state specified
by the application.
Return Value
No return value.
Remarks
This method is equivalent to launching one of the commands associated
with a file's shortcut menu. Each command is identified by a verb
string. The supported verbs vary from file to file. The most commonly
supported verb is "open", which is also usually the default verb.
Others might be supported only by certain types of files. For further
discussion of Shell verbs, see Launching Applications or Extending
Shortcut Menus.
This method is not currently available in Microsoft Visual Basic.
Examples
The following example uses ShellExecute to open Microsoft Notepad.
Proper usage is shown for Microsoft JScript and Visual Basic Scripting
Edition (VBScript).
<script language="VBScript">
function fnShellExecuteVB()
dim objShell
set objShell = CreateObject("Shell.Application")
objShell.ShellExecute "notepad.exe", "", "", "open", 1
set objShell = nothing
end function
</script>
Now all COM calls look like this HResult = methodcall(param1, param2, ..., paramn, OUTPARAM).
VB pretends it OUTPARAM = methodcall(param1, Param2, ..., paramn) with HResult appearing in the err.object.
So errors will still fire, it's just that it doesn't wait to find out.

How to set "Run as administrator" flag on shortcut created by MSI installer

I have a Setup and Deployment project in Visual Studio 2010.
I would like the installer to create two shortcuts to the executable of another project in my solution. One normal shortcut that simply runs the application using current credentials and another which has the Run as administrator flag set, thereby ensuring that the user is asked for credentials with administrative rights when clicking the shortcut.
Running the application with administrative rights enables certain features that are otherwise not available.
Setting this flag doesn't seem to be possible at first glance. Can this be done directly in Visual Studio? If not, are there any other options?
Edit: If not, is it possible to modify the shortcut programmatically using a custom installer class?
I know this is quite an old question, but I needed to find an answer and I thought I could help other searchers. I wrote a small function to perform this task in VBScript (pasted below). It is easily adapted to VB.net / VB6.
Return codes from function:
0 - success, changed the shortcut.
99 - shortcut flag already set to run as administrator.
114017 - file not found
114038 - Data file format not valid (specifically the file is way too small)
All other non-zero = unexpected errors.
As mentioned by Chada in a later post, this script will not work on msi Advertised shortcuts. If you use this method to manipulate the bits in the shortcut, it must be a standard, non-advertised shortcut.
References:
MS Shortcut LNK format: http://msdn.microsoft.com/en-us/library/dd871305
Some inspiration: Read and write binary file in VBscript
Please note that the function does not check for a valid LNK shortcut. In fact you can feed it ANY file and it will alter Hex byte 15h in the file to set bit 32 to on.
If copies the original shortcut to %TEMP% before amending it.
Daz.
'# D.Collins - 12:58 03/09/2012
'# Sets a shortcut to have the RunAs flag set. Drag an LNK file onto this script to test
Option Explicit
Dim oArgs, ret
Set oArgs = WScript.Arguments
If oArgs.Count > 0 Then
ret = fSetRunAsOnLNK(oArgs(0))
MsgBox "Done, return = " & ret
Else
MsgBox "No Args"
End If
Function fSetRunAsOnLNK(sInputLNK)
Dim fso, wshShell, oFile, iSize, aInput(), ts, i
Set fso = CreateObject("Scripting.FileSystemObject")
Set wshShell = CreateObject("WScript.Shell")
If Not fso.FileExists(sInputLNK) Then fSetRunAsOnLNK = 114017 : Exit Function
Set oFile = fso.GetFile(sInputLNK)
iSize = oFile.Size
ReDim aInput(iSize)
Set ts = oFile.OpenAsTextStream()
i = 0
Do While Not ts.AtEndOfStream
aInput(i) = ts.Read(1)
i = i + 1
Loop
ts.Close
If UBound(aInput) < 50 Then fSetRunAsOnLNK = 114038 : Exit Function
If (Asc(aInput(21)) And 32) = 0 Then
aInput(21) = Chr(Asc(aInput(21)) + 32)
Else
fSetRunAsOnLNK = 99 : Exit Function
End If
fso.CopyFile sInputLNK, wshShell.ExpandEnvironmentStrings("%temp%\" & oFile.Name & "." & Hour(Now()) & "-" & Minute(Now()) & "-" & Second(Now()))
On Error Resume Next
Set ts = fso.CreateTextFile(sInputLNK, True)
If Err.Number <> 0 Then fSetRunAsOnLNK = Err.number : Exit Function
ts.Write(Join(aInput, ""))
If Err.Number <> 0 Then fSetRunAsOnLNK = Err.number : Exit Function
ts.Close
fSetRunAsOnLNK = 0
End Function
This is largely due to the fact that Windows Installer uses 'Advertised shortcuts' for the Windows Installer packages.
There is no way inherently to disable this in Visual Studio, but it is possible to modify the MSI that is produced to make sure that it does not use advertised shortcuts (or uses only one). There are 2 ways of going about this:
If your application uses a single exe or two - Use ORCA to edit the MSI. Under the shortcuts table, change the Target Entry to "[TARGETDIR]\MyExeName.exe" - where MyExeName is the name of your exe - this ensures that that particular shortcut is not advertised.
Add DISABLEADVTSHORTCUTS=1 to the the property Table of the MSI using ORCA or a post build event (using the WiRunSQL.vbs script). If you need more info on this let me know. This disables all advertised shortcuts.
it may be better to use the first approach, create 2 shortcuts and modify only one in ORCA so that you can right click and run as admin.
Hope this helps
This is not supported by Windows Installer. Elevation is usually handled by the application through its manifest.
A solution is to create a wrapper (VBScript or EXE) which uses ShellExecute with runas verb to launch your application as an Administrator. Your shortcut can then point to this wrapper instead of the actual application.
Sorry for the confusion - I now understand what you are after.
There are indeed ways to set the shortcut flag but none that I know of straight in Visual Studio. I have found a number of functions written in C++ that set the SLDF_RUNAS_USER flag on a shortcut.
Some links to such functions include:
http://blogs.msdn.com/b/oldnewthing/archive/2007/12/19/6801084.aspx
http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/a55aa70e-ae4d-4bf6-b179-2e3df3668989/
Another interesting discussion on the same topic was carried out at NSIS forums, the thread may be of help. There is a function listed that can be built as well as mention of a registry location which stores such shortcut settings (this seems to be the easiest way to go, if it works) - I am unable to test the registry method at the moment, but can do a bit later to see if it works.
This thread can be found here: http://forums.winamp.com/showthread.php?t=278764
If you are quite keen to do this programatically, then maybe you could adapt one of the functions above to be run as a post-install task? This would set the flag of the shortcut after your install but this once again needs to be done on Non-Advertised shortcuts so the MSI would have to be fixed as I mentioned earlier.
I'll keep looking and test out the registry setting method to see if it works and report back.
Chada
I needed to make my application to be prompted for Administator's Rights when running from Start Menu or Program Files.
I achieved this behavior after setting in \bin\Debug\my_app.exe 'Run this program as administator' checkbox to true. ( located in Properties\Compatibility section ).
While installing project, this file was copied to the Program Files (and therefore the shortcut in the Start Menu) with needed behavior.
Thanks,
Pavlo

How to open a file from network drive/path with default program?

from my application I want to open files (jpg, pdf, ..) with the default windows-program from network drives. I know start, but it doesn't seem to work for network paths.
I tried the following commands, but all I get is the windows dialog telling me that he doesn't know how to open that file and whether I want to use a web-service to ask for a programm or choose manually.
From cmd.exe (P:\ is a network drive):
cmd /c "start \server\path\to\image.jpg"
> cmd /c "start P:\path\to\image.jpg"
The path to the file is correct and clicking on it in the explorer works fine.
Thanks
UPDATE: I found the problem. See my answer below.
I think the function you need is ShellExecute - it would look something like this:
ShellExecute(ParentWindowHandl, "open", "Z:\SQLWriter.doc", NULL, SW_SHOWNORMAL);
P.S. I know I should post this as comment, but can't comment on all posts yet.
I tried these two commands:
start Z:\SQLWriter.doc
start \192.168.10.230\MyFolder\SQLWriter.doc
Both the commands worked perfectly. I didn't get any error messages.
You can use these if you want it to launch.
SHELLEXECUTEINFO ExecuteInfo;
memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
ExecuteInfo.cbSize = sizeof(ExecuteInfo);
ExecuteInfo.fMask = 0;
ExecuteInfo.hwnd = 0;
ExecuteInfo.lpVerb = "open"; // Operation to perform
ExecuteInfo.lpFile = "cmd.exe"; // Application name
ExecuteInfo.lpParameters = "start P:\Myfile.jpg"; // Additional parameters
ExecuteInfo.lpDirectory = 0; // Default directory
ExecuteInfo.nShow = SW_SHOW;
ExecuteInfo.hInstApp = 0;
if(ShellExecuteEx(&ExecuteInfo) == FALSE)
Or you can go through this link: http://www.codeguru.com/forum/showthread.php?t=302501
Ok, I have found the problem. Seems like the windows registry was a bit confused.
As commented before, other files like text and doc work, so the only problem was JPEG files.
Double Clicking them in the Windows Explorer worked fine for them, but using the start command showed me the popup described above. Selecting a program here once and marking it as permanent resolved my problem. Further calls with start now correctly open the image directly.

Detect if the contents of a folder have changed?

Conditions:
Windows 98 SE
WMI not available
I have code that looks like this, written using my steroidal wrapping of VBScript using MSScript.
do
a = files.collectfiles( "c:\userver", "" )
for i = 0 to ubound( a )
f = a(i)
if strings.endswith( f, ".usv" ) then
d = files.readfilee( f )
on error resume next
executeglobal d
nErr = err.number
sErr = err.description
on error goto 0
if nErr <> 0 then
trace "*** Error " & nErr & ", " & sErr
end if
files.deletefile f
end if
next
system.sleep 10
system.cooperate
loop
There's a lot of disk activity with that call to files.collectfiles. Is there some way of detecting a change in the contents of a folder without actually scanning the folder for files?
There is a sample which claims to work on all versions from Win95 up to at leas WinXP. Developed under Win98 with VB5. Using the (then? provided links to the docu below) undocumented SHChangeNotify* Functions.
SHChangeNotifyRegister: Receive Shell Change Notifications
SHChangeNotifyRegister Function
SHChangeNotifyDeregister Function
There is another solution using ReadDirectoryChangesW here:
VB6 WinAPI ReadDirectoryChangesW (check the 5th post from Yang Kok Wah)
Define "change in the contents of a folder".
If it means that a file was added, deleted, or renamed, then the modified timestamp of the folder is updated whenever such an event occurs.
If you're instead wanting to know when files are modified, then you'll need to read them.
That said, looking at what you're trying to do (scan a folder for new .usv files, and process them and delete them), then just keeping track of the timestamp on the folder and updating it right before you call collectfiles is best (note that the correct time to log is just BEFORE calling collectfiles, otherwise you run the risk of not waking up if a file gets added during the collectfiles call or immediately afterward).
You specifically asked for something in VB and running on win98 and I have no answer for this, but MS has a c/win32 example on how to achieve this on Windows2000+ with FindFirstChangeNotification. Another thing is that apparently "FileSystemWatcher" in .NET is not working/supported on Win98. What is my point? There maybe is no easy solution for this and you have to come up with something on your own.

Resources