F# Run Powershell Script As Target - powershell

Trying to run a powershell script using F# FAKE but nothing happens... there are no errors, the target loads but nothing actually is run.
// include Fake lib
#r "packages/FAKE/tools/FakeLib.dll"
#r "System.Management.Automation"
open System
open System.IO
open System.Diagnostics
open System.Management.Automation
Target "Powershell" <| fun _ ->
PowerShell.Create()
.AddScript("& 'build-database.ps1'")
.AddParameter("BuildVersion", version)
.AddParameter("Debug", "")
.Invoke()
|> Seq.iter (printfn "%O")
// Dependencies
"Clean"
==> "Powershell"
// start build
RunTargetOrDefault "Powershell"
Am I missing something? Without any error I am not sure what the issue is.
* Updated *
This is the powershell script I am testing with, FAKE does nothing.
New-Item c:\AnEmptyFile.txt -ItemType file

I finally figured out another way to do it that works. In case someone else has the need to call a powershell script from within F# FAKE the following method worked for me.
Target "Powershell" (fun _ ->
let p = new System.Diagnostics.Process();
p.StartInfo.FileName <- "cmd.exe";
p.StartInfo.Arguments <- ("/c powershell -ExecutionPolicy Unrestricted .\\script.ps1)
p.StartInfo.RedirectStandardOutput <- true
p.StartInfo.UseShellExecute <- false
p.Start() |> ignore
printfn "Processing..."
printfn "%A" (p.StandardOutput.ReadToEnd())
printfn "Finished"
)

Its possible to use Shell.Execute and invoke powershell.exe:
Target "ImportDb" (fun _ ->
Shell.Exec("powershell.exe", "-NoProfile -ExecutionPolicy Bypass -File script.ps1") |> ignore)

Related

Auto Login SAP GUI with powershell script

I'm trying to write a script that automatically logs into an SAP system via SAP GUI. I want the SAP GUI fields to be filled automatically with the script below.
Can you tell me, if I'm on the right way? How can I let it work?
#-Begin-----------------------------------------------------------------
#-Includes------------------------------------------------------------
."$PSScriptRoot\COM.ps1"
$hWSH = Create-Object "Wscript.Shell"
$hWSH.Popup("testmessage", 2, "goto", 1)
Free-Object $hWSH
#-Signatures----------------------------------------------------------
$Sig = #'
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
'#
# FindWindow function---------------------------------------------
$Win32 = Add-Type -Namespace Win32 -Name Funcs -MemberDefinition $Sig -PassThru
#-Set the path to the SAP GUI directory-------------------------------
$SAPGUIPath = "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\"
# SAP system ID-----------------------------------------------
$SID = "test.lan"
#instance number of the SAP system---------------------------
$InstanceNo = "10"
#-Start SAP GUI---------------------------------------------------
$SAPGUI = $SAPGUIPath + "sapgui.exe"
& $SAPGUI $SID $InstanceNo
#-Wait until the session is available---------------------------------
While ($Win32::FindWindow("SAP_FRONTEND_SESSION", "SAP") -eq 0) {
Start-Sleep -Milliseconds 250
}
#-Logon to SAP --------------------------------------------
$user="test"
$SAPGUI.document.getElementById("Benutzer").value= "$user"
$SAPGUI.document.getElementById("loginform").submit()
```
You could use SAP shortcut:
cd "c:\Program Files (x86)\SAP\FrontEnd\SAPgui\"
sapshcut -guiparm="[hostname] [installation number]" -system=[system id] -client=[client] -user=[user name] -pw=[password]
Replace the parameters (square brackets) with the appropriate values. You will see a confirmation popup when you execute this command for the first time (for a specific set of parameters), but you can disable the dialog for future automatic logins.
You may omit parameter -guiparm="[hostname] [installation number]" if the system ID is created in SAPlogon.

How to kick off ExtendScript JSX script from Powershell

I want to be able to execute an Adobe Illustrator ExtendScript via Windows Powershell. I believe this should be possible due to this answer that describes using VB via COM.
This is my Powershell script:
$illustratorRef = New-Object -ComObject Illustrator.Application
$conversionScript = New-Object -ComObject Scripting.FileSystemObject
$scriptFile = $conversionScript.OpenTextFile("C:\ws\ArtConversion\alert-test.jsx")
$fileContents = $scriptFile.ReadAll()
$scriptFile.Close()
$fileToRun = $fileContents + "main(arguments)"
$args = "line1", "line2"
$illustratorRef.DoJavaScript($fileToRun, $args, 1)
Here is the alert-test.jsx script:
function main(argv) {
alert('message: ' + argv[0]);
return argv[0];
}
Running the Powershell script opens Illustrator, but throws the following error upon encountering $illustratorRef.DoJavaScript:
Library not registered. (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED))
I am using Adobe Illustrator 2019 CC (64bit) and Powershell 5.1.16299.666
I achieved my goal, but wasn't able to do it 100% with Powershell.
The 2017 Adobe Illustrator Scripting Guide contains this statement on page 22:
In VBScript, there are several ways to create an instance of Illustrator.
When referring to JavaScript however, it says:
Information on launching Illustrator from JavaScript is beyond the scope of this guide.
I couldn't find any official documentation on how to programmatically start Illustrator on Windows using other languages besides VB, so I ended up letting my Powershell script handle the heavy lifting of directory traversal and logging, while having it open Illustrator by means of a Visual Basic script.
The call from Powershell into VB looks like this:
$convertFile = "cmd /C cscript .\run-illustrator-conversion.vbs $arg1, $arg2"
$output = Invoke-Expression $convertFile
The VB script ended up looking like this:
Dim appRef
Dim javaScriptFile
Dim argsArr()
Dim fsObj : Set fsObj = CreateObject("Scripting.FileSystemObject")
Dim jsxFile : Set jsxFile = fsObj.OpenTextFile(".\script-to-run.jsx", 1, False)
Dim fileContents : fileContents = jsxFile.ReadAll
jsxFile.Close
Set jsxFile = Nothing
Set fsObj = Nothing
javascriptFile = fileContents & "main(arguments);"
Set appRef = CreateObject("Illustrator.Application.CS5")
ReDim argsArr(Wscript.Arguments.length - 1)
For i = 0 To Wscript.Arguments.length - 1
argsArr(i) = Wscript.Arguments(i)
Next
Wscript.Echo appRef.DoJavaScript(javascriptFile, argsArr, 1)
Note: Check scripting guide to get correct string for your version of Illustrator.

PowerShell crashes on `if ( $? = $false )`

I'm playing with PowerShell and I've encountered a crash that I can easily reproduce on my computer.
I'm not sure if the code is correct. However, running the following piece makes powershell.exe and powershell_ise.exe crash. I guess that my use of if ( $? = $false ) is wrong, but crash should not happen in such case. Removing If statement helps to avoid the crash.
Is there anything I'm missing?
I'm running Windows 10 Pro and PowerShell 5.1.14393.206.
Update 1
OK, thanks to #Martin I know that I mistakenly used = instead of -eq. But why this crash happens?
Update 2
Filed a bug report to PowerShell UserVoice: https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/16977433-assigning-a-value-to-false-crashes
Update 3
It seems to be a known bug: https://github.com/PowerShell/PowerShell/issues/2243 that should be fixed soon https://github.com/PowerShell/PowerShell/pull/2320
Test-Path "C:\test"
if ( $? = $false ) {
Out-Host "Hello World"
}
Fault bucket 127386360339, type 5
Event Name: PowerShell
Response: Not available
Cab Id: 0
Problem signature:
P1: powershell.exe
P2: 10.0.14393.206
P3: stem.Management.Automation.PSInvalidCast
P4: stem.Management.Automation.PSInvalidCast
P5: ation.LanguagePrimitives.ThrowInvalidCastException
P6: ation.LanguagePrimitives.ThrowInvalidCastException
P7: Pipeli..ution Thread
P8:
P9:
P10:
Your code is wrong. You are assigning $false to the question mark variable which is a read-only variable. You probably want to replace the = with -eq:
Test-Path "C:\test"
if ( $? -eq $false ) {
Out-Host "Hello World"
}

Starting cmd-console from another program by ShellExecute: What to enther that cmd stays open after script finishes?

I am starting my ps-script by Windows' ShellExecuteW(..):
#import "shell32.dll"
int ShellExecuteW(int hWnd,int lpVerb,string lpFile,string lpParameters,string lpDirectory,int nCmdShow);
#import
....
string psDir = "C:\\Users...\\WindowsPowerShell";
string param = "-file loadPOP2emails.ps1";
int ret = ShellExecuteW(0,0, "powershell.exe", param, psDir, SW_SHOW);
What do I have to enter in the param-string that the console remains open after the script has finished?
Any hint that I can try?
Thanks in advance
The parameter needed to keep powershell open is NoExit
string param = "-NoExit -file loadPOP2emails.ps1";

How can you create pop up messages in a batch script?

I need to know how to make popup messages in batch scripts without using VBScript or KiXtart or any other external scripting/programming language.
I have zero clue about this... had no starting point even.
I am aware of NET SEND but the Messenger service is disabled in my current environment.
msg * "Enter Your Message"
Does this help ?
With regard to LittleBobbyTable's answer - NET SEND does not work on Vista or Windows 7. It has been replaced by MSG.EXE
There is a crude solution that works on all versions of Windows - A crude popup message can be sent by STARTing a new cmd.exe window that closes once a key is pressed.
start "" cmd /c "echo Hello world!&echo(&pause"
If you want your script to pause until the message box is dismissed, then you can add the /WAIT option.
start "" /wait cmd /c "echo Hello world!&echo(&pause"
You can take advantage of CSCRIPT.EXE or WSCRIPT.EXE (which have been present in every version of Windows since, I believe, Windows 95) like this:
echo msgbox "Hey! Here is a message!" > %tmp%\tmp.vbs
cscript /nologo %tmp%\tmp.vbs
del %tmp%\tmp.vbs
or
echo msgbox "Hey! Here is a message!" > %tmp%\tmp.vbs
wscript %tmp%\tmp.vbs
del %tmp%\tmp.vbs
You could also choose the more customizeable PopUp command. This example gives you a 10 second window to click OK, before timing out:
echo set WshShell = WScript.CreateObject("WScript.Shell") > %tmp%\tmp.vbs
echo WScript.Quit (WshShell.Popup( "You have 10 seconds to Click 'OK'." ,10 ,"Click OK", 0)) >> %tmp%\tmp.vbs
cscript /nologo %tmp%\tmp.vbs
if %errorlevel%==1 (
echo You Clicked OK
) else (
echo The Message timed out.
)
del %tmp%\tmp.vbs
In their above context, both cscript and wscript will act the same. When called from a batch file, bot cscript and wscript will pause the batch file until they finish their script, then allow the file to continue.
When called manually from the command prompt, cscript will not return control to the command prompt until it is finished, while wscript will create a seprate thread for the execution of it's script, returning control to the command prompt even before it's script has finished.
Other methods discussed in this thread do not cause the execution of batch files to pause while waiting for the message to be clicked on. Your selection will be dictated by your needs.
Note: Using this method, multiple button and icon configurations are available to cover various yes/no/cancel/abort/retry queries to the user: https://technet.microsoft.com/en-us/library/ee156593.aspx
Few more ways (in all of them the script waits for button pressing unlike msg.exe).
1) The geekiest and hackiest - it uses the IEXPRESS to create small exe that will create a pop-up with a single button (it can create two more types of pop-up messages).Works on EVERY windows from XP and above:
;#echo off
;setlocal
;set ppopup_executable=popupe.exe
;set "message2=%~1"
;
;del /q /f %tmp%\yes >nul 2>&1
;
;copy /y "%~f0" "%temp%\popup.sed" >nul 2>&1
;(echo(FinishMessage=%message2%)>>"%temp%\popup.sed";
;(echo(TargetName=%cd%\%ppopup_executable%)>>"%temp%\popup.sed";
;(echo(FriendlyName=%message1_title%)>>"%temp%\popup.sed"
;
;iexpress /n /q /m %temp%\popup.sed
;%ppopup_executable%
;rem del /q /f %ppopup_executable% >nul 2>&1
;pause
;endlocal
;exit /b 0
[Version]
Class=IEXPRESS
SEDVersion=3
[Options]
PackagePurpose=InstallApp
ShowInstallProgramWindow=1
HideExtractAnimation=1
UseLongFileName=0
InsideCompressed=0
CAB_FixedSize=0
CAB_ResvCodeSigning=0
RebootMode=N
InstallPrompt=%InstallPrompt%
DisplayLicense=%DisplayLicense%
FinishMessage=%FinishMessage%
TargetName=%TargetName%
FriendlyName=%FriendlyName%
AppLaunched=%AppLaunched%
PostInstallCmd=%PostInstallCmd%
AdminQuietInstCmd=%AdminQuietInstCmd%
UserQuietInstCmd=%UserQuietInstCmd%
SourceFiles=SourceFiles
[SourceFiles]
SourceFiles0=C:\Windows\System32\
[SourceFiles0]
%FILE0%=
[Strings]
AppLaunched=subst.exe
PostInstallCmd=<None>
AdminQuietInstCmd=
UserQuietInstCmd=
FILE0="subst.exe"
DisplayLicense=
InstallPrompt=
;
Example Usage (if you save the script as expPopup.bat):
call expPopup.bat "my Message"
2) Using MSHTA. Also works on every windows machine from XP and above (despite yhe OP do not wants "external" languages the jsvascript here is minimized).Should be saved as .bat:
#if (true == false) #end /*!
#echo off
mshta "about:<script src='file://%~f0'></script><script>close()</script>" %*
goto :EOF */
alert("Hello, world!");
or in one line:
mshta "about:<script>alert('Hello, world!');close()</script>"
or
mshta "javascript:alert('message');close()"
or
mshta.exe vbscript:Execute("msgbox ""message"",0,""title"":close")
3) Here's parametrized .bat/jscript hybrid (should be saved as bat) .It again uses jscript despite the OP request but as it is a bat it can be called as a bat file without worries.It uses POPUP which allows a little bit more control than the more populae MSGBOX.It uses WSH ,but not MSHTA like in the example above.
#if (#x)==(#y) #end /***** jscript comment ******
#echo off
cscript //E:JScript //nologo "%~f0" "%~nx0" %*
exit /b 0
#if (#x)==(#y) #end ****** end comment *********/
var wshShell = WScript.CreateObject("WScript.Shell");
var args=WScript.Arguments;
var title=args.Item(0);
var timeout=-1;
var pressed_message="button pressed";
var timeout_message="timedout";
var message="";
function printHelp() {
WScript.Echo(title + "[-title Title] [-timeout m] [-tom \"Time-out message\"] [-pbm \"Pressed button message\"] [-message \"pop-up message\"]");
}
if (WScript.Arguments.Length==1){
runPopup();
WScript.Quit(0);
}
if (args.Item(1).toLowerCase() == "-help" || args.Item(1).toLowerCase() == "-h" ) {
printHelp();
WScript.Quit(0);
}
if (WScript.Arguments.Length % 2 == 0 ) {
WScript.Echo("Illegal arguments ");
printHelp();
WScript.Quit(1);
}
for (var arg = 1 ; arg<args.Length;arg=arg+2) {
if (args.Item(arg).toLowerCase() == "-title") {
title = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-timeout") {
timeout = parseInt(args.Item(arg+1));
if (isNaN(timeout)) {
timeout=-1;
}
}
if (args.Item(arg).toLowerCase() == "-tom") {
timeout_message = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-pbm") {
pressed_message = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-message") {
message = args.Item(arg+1);
}
}
function runPopup(){
var btn = wshShell.Popup(message, timeout, title, 0x0 + 0x10);
switch(btn) {
// button pressed.
case 1:
WScript.Echo(pressed_message);
break;
// Timed out.
case -1:
WScript.Echo(timeout_message);
break;
}
}
runPopup();
example usage (it will wait 10 seconds to press the yes button):
jsPopup.bat -title CoolTitile -t 10 -tom "time out" -pbm "press the button please" -message "love and peace"
4) and one jscript.net/.bat hybrid (should be saved as .bat) .This time it uses .NET and compiles a small .exe file that could be deleted:
#if (#X)==(#Y) #end /****** silent jscript comment ******
#echo off
::::::::::::::::::::::::::::::::::::
::: compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
::if exist "%~n0.exe" goto :skip_compilation
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"%~n0.exe" "%~f0"
::::::::::::::::::::::::::::::::::::
::: end of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
::
::::::::::
"%~n0.exe" %*
::::::::
::
endlocal
exit /b 0
****** end of jscript comment ******/
import System;
import System.WIndows;
import System.Windows.Forms
var arguments:String[] = Environment.GetCommandLineArgs();
MessageBox.Show(arguments[1],arguments[0]);
Example usage:
netPopUp.bat "Roger That"
5) and at the end one single call to powershell that creates a pop-up (can be called from command line or from batch if powershell is installed):
powershell [Reflection.Assembly]::LoadWithPartialName("""System.Windows.Forms""");[Windows.Forms.MessageBox]::show("""Hello World""", """My PopUp Message Box""")
6) Though msg solution is already post as answer here's a better way to be used:
msg * /self /w "hello world"
/self is a not documented switch that will force msg to send the message only to the current user.
msg * Hello world
works for me..
So, i present cmdmsg.bat.
The code is:
#echo off
echo WScript.Quit MsgBox(%1, vbYesNo) > #.vbs
cscript //nologo #.vbs
echo. >%ERRORLEVEL%.cm
del #.vbs
exit /b
And a example file:
#echo off
cls
call cmdmsg "hi select yes or no"
if exist "6.cm" call :yes
if exist "7.cm" call :no
:yes
cls
if exist "6.cm" del 6.cm
if exist "7.cm" del 7.cm
echo.
echo you selected yes
echo.
pause >nul
exit /b
:no
cls
if exist "6.cm" del 6.cm
if exist "7.cm" del 7.cm
echo.
echo aw man, you selected no
echo.
pause >nul
exit /b
I put together a script based on the good answers here & in other posts
You can set title timeout & even sleep to schedule it for latter & \n for new line
also you get back the key press into a variable (%pop.key%).
Here is my code
Your best bet is to use NET SEND as documented on Rob van der Woude's site.
Otherwise, you'll need to use an external scripting program. Batch files are really intended to send messages via ECHO.
This is very simple beacuse i have created a couple lines of code that will do this for you
So set a variable as msg and then use this code. it popup in a VBS message box.
CODE:
#echo off
echo %msg% >vbs.txt
copy vbs.txt vbs.vbs
del vbs.txt
start vbs.vbs
timeout /t 1
del vbs.vbs
cls
This is just something i came up with it should work for most of your message needs and it also works with Spaces unlike some batch scripts
It's easy to make a message, here's how:
First open notpad and type:
msg "Message",0,"Title"
and save it as Message.vbs.
Now in your batch file type:
Message.vbs %*
msg * message goes here
That method is very simple and easy and should work in any batch file i believe. The only "downside" to this method is that it can only show 1 message at once, if there is more than one message it will show each one after the other depending on the order you put them inside the code. Also make sure there is a different looping or continuous operator in your batch file or it will close automatically and only this message will appear. If you need a "quiet" background looping opperator, heres one:
pause >nul
That should keep it running but then it will close after a button is pressed.
Also to keep all the commands "quiet" when running, so they just run and dont display that they were typed into the file, just put the following line at the beginning of the batch file:
#echo off
I hope all these tips helped!