AutoIt: run a program selected with FileOpenDialog? - scripting

I need to make a script that allows a user to run a software with certain parameters (that should be typed in). So, first step, select the exe. Second, a text input box should allow the user to enter the parameters. I can't get the first step done.
I tried with the second example found here: FileOpenDialog
The only modification is a Run command I added. When I run the script, I see the complete file path for the executable but nothing runs. I don't see an error either:
include <FileConstants.au3>
include <MsgBoxConstants.au3>
Example()
Func Example()
; Create a constant variable in Local scope of the message to display in FileOpenDialog.
Local Const $sMessage = "Select a single file of any type."
; Display an open dialog to select a file.
Local $sFileOpenDialog = FileOpenDialog($sMessage, #WindowsDir & "\", "All (*.*)", $FD_FILEMUSTEXIST)
If #error Then
; Display the error message.
MsgBox($MB_SYSTEMMODAL, "", "No file was selected.")
; Change the working directory (#WorkingDir) back to the location of the script directory as FileOpenDialog sets it to the last accessed folder.
FileChangeDir(#ScriptDir)
Else
; Change the working directory (#WorkingDir) back to the location of the script directory as FileOpenDialog sets it to the last accessed folder.
FileChangeDir(#ScriptDir)
; Replace instances of "|" with #CRLF in the string returned by FileOpenDialog.
$sFileOpenDialog = StringReplace($sFileOpenDialog, "|", #CRLF)
; Display the selected file.
MsgBox($MB_SYSTEMMODAL, "", "You chose the following file:" & #CRLF & $sFileOpenDialog)
Run($sFileOpenDialog)
EndIf
EndFunc ;==>Example

#include <FileConstants.au3>
Example()
Func Example()
; Create a constant variable in Local scope of the message to display in FileOpenDialog.
Local Const $sMessage = "Select a single file of any type."
; Display an open dialog to select a file.
Local $sFileOpenDialog = FileOpenDialog($sMessage, #WindowsDir & "\", "All (*.*)", $FD_FILEMUSTEXIST)
If #error Then
; Display the error message.
MsgBox(1, "", "No file was selected.")
; Change the working directory (#WorkingDir) back to the location of the script directory as FileOpenDialog sets it to the last accessed folder.
FileChangeDir(#ScriptDir)
Else
; Change the working directory (#WorkingDir) back to the location of the script directory as FileOpenDialog sets it to the last accessed folder.
FileChangeDir(#ScriptDir)
; Replace instances of "|" with #CRLF in the string returned by FileOpenDialog.
$sFileOpenDialog = StringReplace($sFileOpenDialog, "|", #CRLF)
; Display the selected file.
MsgBox(1, "", "You chose the following file:" & #CRLF & $sFileOpenDialog)
Run($sFileOpenDialog)
EndIf
EndFunc ;==>Example
This works for me.
I dont know this "include MsgBoxConstants.au3" wich i think is unnecessary.
Lg Teifun2

You need to add the # before the include. Also the 2nd include has to be Constants.au3. When I do these changes I can successfully start any application with your code.
#include <FileConstants.au3>
#include <Constants.au3>

Related

Powershell Excel - Using new range for search gives errors for old range

I am a complete beginner to Microsoft PowerShell, but I have worked with C++, Java, and C#. I was working on this small script for my job, and I came across a strange issue that is likely due to me not properly understanding how ranges work. This script is supposed to open up an Excel workbook, search each sheet for a name, and give the names that match along with their information. The problem is when I set the range again to search for the starting column index of information (in this case, the column to the right of the column labeled "Description"), it breaks the range when it searches for more than one match of the same last name.
I have a do-while loop that uses worksheet.range.entirerow.findnext() so that I can find multiple with the same last name. This works until I used a new range, worksheet.range.entirecolumn.find(). This is my latest code of what I tried, but I have already tried hardcoding $Range to 5 (which worked, but I want it to be dynamic) or used a new variable $RowRange (which didn't fix the issue). If I understood correctly, the range is like the current selection of two or more cells, so why can I not reset it or use a new variable? It does not loop, so I only keep finding the first name in each sheet.
P.S. As a side question, I had an issue of shutting down the process of this excel document I want to open in the background without shutting down other Excel workbooks. For some reason, using Get-Process EXCEL | Stop-Process -Force; shuts down ALL of my open workbooks. I commented it out, but I'm worried about the process not quite ending when it's done executing this code.
# Prepare output file for results
$FileName = "TEST";
$OutputFile = "Results.txt";
Remove-Item $OutputFile;
New-Item $OutputFile -ItemType file;
$Writer = [System.IO.StreamWriter] $OutputFile;
Clear-Host
Write-Host Starting...
# Start up Excel
$Excel = New-Object -ComObject Excel.Application;
$File = $FileName + ".xlsx";
# Prompt user for last name of person to search for (and write to the Results.txt output file)
Clear-Host
Write-Host Search for users in each region by their last name.
$SearchLastName = Read-Host -Prompt "Please input the person's last name";
Write-Host Searching for person...;
$Writer.WriteLine("Name Search: " + $SearchLastName);
$Writer.WriteLine("");
# Then open it without it being made visible to the user
$Excel.Visible = $false;
$Excel.DisplayAlerts = $true;
$Excel.Workbooks.Open($File);
# For each worksheet, or tab, search for the name in the first column (last names)
$Excel.Worksheets | ForEach-Object{
$_.activate();
$Range = $_.Range("A1").EntireColumn;
# Note: To search for text in the ENTIRETY of a cell, need to use the find method's lookat
# parameter (use 1). Otherwise, if searching for Smith, Nesmith also gets detected.
$SearchLast = $Range.find($SearchLastName,[Type]::Missing,[Type]::Missing,1);
$Writer.WriteLine($_.name + ": ");
if ($SearchLast -ne $null) {
$FirstRow = $SearchLast.Row;
do {
# If a first name was found, get the first name too
$FirstName = $_.Cells.Item($SearchLast.Row, $SearchLast.Column + 1).value();
# Then display in proper order
$Writer.WriteLine(" " + $SearchLast.value() + "," + $FirstName);
# From here, find the relevant information on that person
# Search for the column labeled "Description", the starting column is the next one, ending column is the number of used columns
$BeginCol = $_.Range("A1").EntireRow.find("Description",[Type]::Missing,[Type]::Missing,1).Column + 1;
$MaxColumns = $_.UsedRange.Columns.Count;
# Check each column for relevant information. If there are no extra rows after "Description" just skip
for ($i = $BeginCol; $i -le $MaxColumns; $i++) {
# The information of the current cell, found by the row of the name and the current row
$CurrentCell = $_.Cells.Item($SearchLast.Row, $i);
# Only add the description if it exists.
if (!([string]::IsNullOrEmpty($CurrentCell.value2))) {
$Description = $_.Cells.Item(1,$i).text();
# Concatenate the description with it's information.
$Display = " - (" + $Description + ": " + $CurrentCell.text() + ")";
# Display the information
$Writer.WriteLine($Display);
}
}
$Writer.WriteLine("");
# Keep searching that name in the current workbook until it finds no more
$SearchLast = $Range.FindNext($SearchLast);
} while (($SearchLast -ne $null) -and ($SearchLast.Row -ne $FirstRow));
} else {
$Writer.WriteLine("Not Found");
}
$Writer.WriteLine("");
};
# Cleaning up the environment
$Writer.close();
$Excel.Workbooks.Item($FileName).close();
$Excel.Quit();
# Force quit the Excel process after quitting
# Get-Process EXCEL | Stop-Process -Force;
# Then remove the $Excel com object to ready it for garbage collection
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel);
# Then, open up the Results.txt file
Invoke-Item Results.txt;

Unable to save the file in specified location using Autoit

Followed the below steps to save a file in desired location:
Step1: Save As window getting opened(with the default downloads location, with file name as DOC)
Step2: entering the file name as "D:\temp\sample.pdf" (which is getting entered in the edit bar)
Step3: clicking the save button (button clicked, file downloaded in the default location rather than the "D:\temp" location)
I have created an .exe with the below .au3 script
WinWait("[CLASS:#32770]","",10)
Sleep(2000)
ControlSetText("Save As", "", "Edit1", $CmdLine[1])
Sleep(5000)
ControlClick("Save As", "", "Button1");
Sleep(5000)
On clicking save, it is getting saved in the default location rather than the specified location.
The below code, executing the script.
IO.popen('autoit_script.exe D:\temp') #Ruby Code
Is there a way to sort it out?
It depends on the software you are trying to automate but usually this happens because the software is not recognizing there is a change in the file save path box. The problem is in how ControlSetText works. Try using ControlSend with some error checking to make sure the file path you are try to set is getting put in right. Sometimes you have to play with a few different variations to see what works with the software you are automating. Here are two examples you can try:
Example one:
WinWait("[CLASS:#32770]", "", 10)
If Not #error Then ;make sure the window was found
$hWin = WinGetHandle("[CLASS:#32770]") ;get window handle
ControlSetText($hWin, "", "Edit1", $CmdLine[1]) ;set text
ControlFocus($hWin, "", "Edit1") ;just to make sure we have focus
ControlSend($hWin, "", "Edit1", "{ENTER}")) ;should work like click button 1 but you will have to check
;better then a sleep
$hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
Do
Until WinExists($hWin) = 0 Or TimerDiff($hTimer) >= 10000
EndIf
Example two:
WinWait("[CLASS:#32770]", "", 10)
If Not #error Then ;make sure the window was found
$hWin = WinGetHandle("[CLASS:#32770]") ;get window handle
While 1
ControlSetText($hWin, "", "Edit1", "") ;just makes sure there is no text in the control text
ControlFocus($hWin, "", "Edit1") ;just to make sure we have focus
ControlSend($hWin, "", "Edit1", $CmdLine[1])) ;set text using ControlSend
If ControlGetText($hWin, "", "Edit1") = $CmdLine[1] Then ExitLoop ;makes sure that the control got ALL of the text before exiting loop
WEnd
ControlClick($hWin, "", "Button1");
;better then a sleep
$hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
Do
Until WinExists($hWin) = 0 Or TimerDiff($hTimer) >= 10000
EndIf

Running Powershell script with if condition from a .NET app

I have a .net application that successfully runs Powershell commands that it pulls from text files- until I tried doing one that is more complicated and contains an if condition. The script works correctly from a PS console but in .NET I only know how to pass in a string for the script, which after reading the file, it adds extra stuff like vblf and even if I take it out, it won't work. Is this even possible?
.NET Runtime Error: Server was unable to process request. ---> The
term 'False' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or
if a path was included, verify that the path is correct and try again.
.NET code:
'Grab Powershell script from text (.ps1) file
strScript = File.ReadAllText(ScriptFileName)
'inject the arguments into the script
strScript = InsertArguments(strScript, Arguments)
'Open the runspace and create a pipeline if it's not already open
If psRunspace.RunspaceStateInfo.State = RunspaceState.BeforeOpen Then
psRunspace.Open()
End If
Dim MyPipeline As Pipeline = psRunspace.CreatePipeline()
MyPipeline.Commands.AddScript(strScript)
Dim psResults As Collection(Of PSObject) = MyPipeline.Invoke()
Powershell Script, stored in ps1 file:
new-mailbox -name $argument1 -DisplayName $argument1 -UserPrincipalName $argument2 Room -DomainController $argument5
if ($argument4 -eq "False") {
Set-CalendarProcessing $argument1 -BookingWindowInDays 400 -DeleteSubject $false -AutomateProcessing autoaccept -AllBookInPolicy $false -BookInPolicy $argument3 -DomainController $argument5
} else {
Set-CalendarProcessing $argument1 -BookingWindowInDays 400 -DeleteSubject $false -AutomateProcessing autoaccept -AllBookInPolicy $true -DomainController $argument5
}
When this script is read in, here is a substring of what gets pulled into strScript:
-Room -DomainController mcexdct1" & vbLf & "if (False -eq "False") {"
Fixed it by changing the PowerShell script from this:
if ($argument4 -eq "False") {
to this:
if ("$argument4" -eq "False") {
It works with quotation marks around it. I guess the "junk" I was seeing in the script string (like vblf) is normal- I don't work with reading from text files that much.

How to set artwork to an iTunes song using NSApplescript in Xcode?

there are some similars questions here but none involves NSApplescript.
I'm trying to add iTunes artwork to a selected track, my code is:
set newFile to add aFileName as POSIX file to ipod_lib
set current_track to newFile
set jpegFilename to ":temp:artwork.jpg" as string
set data of artwork 1 of current_track to (read (file jpegFilename) as picture)
tell current_track
set name to "Song Name" as string
set artist to "Custom Artist" as string
set album to "Custom Album" as string
set year to "2011" as string
set track number to "1" as number
set track count to "38" as number
end tell
Where aFileName is the path of an mp3.
I'm testing this using Script Debugger 4.5 and it works fine, but when I copy the code to my Xcode project and run it wont set the artwork neither the other meta data.
But if I comment the "set data of artwork.." line, then it does set the other meta data (name, artist, etc)
My Xcode code is:
NSString *scriptote = #"with timeout of 600 seconds\n"
"tell application \"iTunes\"\n"
...
"set newFile to add aFileName as POSIX file to ipod_lib\n"
"set current_track to newFile\n"
"set jpegFilename to \":temp:artwork.jpg\" as string\n"
// If a comment the following line, everything else works, if I left this line, no meta data is set.
"set data of artwork 1 of current_track to (read (file jpegFilename) as picture)\n"
"tell current_track\n"
"set name to \"Song Name\" as string\n"
"set artist to \"Custom Artist\" as string\n"
"set album to \"Custom Album\" as string\n"
"set year to \"2011\" as string\n"
"set track number to \"1\" as number\n"
"set track count to \"38\" as number\n"
"end tell\n"
...
;
if ((ascript = [[NSAppleScript alloc] initWithSource:scriptote])) {
status = [[ascript executeAndReturnError:&errorInfo] stringValue];
if (!errorInfo) {
// do something
NSLog(#"NO Error");
} else {
// process errors
// NSRange errorRange = [[errorInfo objectForKey:#"NSAppleScriptErrorRange"] rangeValue];
NSLog(#"Error\n Error line: ");
}
[ascript release];
}
I have been searching on google for many hours without luck.
I don't want to use ScriptBridge framework because I will need to translate lot of applescripts so its not an option for me right now.
Any help will be greatly appreciated.
Found the problem, in case someone else reach here in the future the problem was with the HFS path format style.
I was getting the path to my artwork using NSSearchPathForDirectoriesInDomains and then replacing all the #"/" for #":" to format the path in HFS style.
The problem is that HFS path format style need a full path including Volume Name and NSSearchPathForDirectoriesInDomain and any other NSFileManager methods return paths starting in /Users/.... and I needed a path like this: Macintosh HD/Users/...
To get the HFS full path I used the following code:
// Get an HFS-style reference to a specified file
// (imagePath is an NSString * containing a POSIX-style path to the artwork image file)
NSURL *fileURL = [NSURL fileURLWithPath:imagePath];
NSString *pathFormatted = (NSString *)CFURLCopyFileSystemPath((CFURLRef)fileURL, kCFURLHFSPathStyle);
That solves the problem, use the pathFormatted string to set the data of artwork and it should work.
Hope this would help someone someday -)

ClearCase : list the content of a directory (ls) using CAL

In ClearCase, you can list the content of a directory using "cleartool ls".
My question is how can I do the same thing using CAL (ClearCase Automation Layer). The reason I prefer the COM API is because I won't have to parse the output of "ls".
So far, I am able to get the VOB and the View successfully, but I didn't find any method for listing the content.
My code so far:
IClearCase cc = new ApplicationClass();
CCVOB vob = cc.get_VOB("\\VOB-name");
CCView view = cc.get_View("ViewTag");
Thank you for your help.
I wrote VonC's answer in C# for those interrested.
string[] files = Directory.GetFiles("View path here", "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
try
{
CCVersion ver = cc.get_Version(file);
Console.WriteLine(ver.Path);
}
catch(Exception) {/*the file is not versioned*/}
}
May be this is a good start:
Set CC = Wscript.CreateObject("ClearCase.Application")
Set DirVer = CC.Version(".")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set Folder = FSO.GetFolder(DirVer.Path)
Wscript.Echo "Files under source control: "
For Each File in Folder.Files
On Error Resume Next
Set Ver = CC.Version(File.Name)
If Err.Number = 0 Then
Wscript.Echo Ver.ExtendedPath
End If
Next
The idea being to use ICCVersion methods to try accessing the version of a file. If it does not return an error, it is indeed a versioned file.
Now I know the file is versioned, how can I remove it (rmname).
Do not use RemoveVersion():
Removes irretrievably the version (equivalent to cleartool rmver)
WARNING! This is a potentially destructive operation. Because CAL does not prompt the user for input under any circumstances, there is no confirmation step when RemoveVersion is invoked. Invoking RemoveVersion is equivalent to running cleartool rmver with the -force option.
Instead use the RemoveName from the ICCElement interface.