Powershell with embedded VBS…

2017-07-27T00:01:03+00:00 November 21st, 2013|Uncategorized|

I recently have been working on a project where the client uses an application that requires a generic username and password to be passed to the database.  To further complicate the matter the users could not know or input the username/password…

To accommodate the project I started working with the logic and how to accomplish this goal.  I started Imprivata (A Single Sign on Application) and AppSense to launch the app at the end of the userinit process.  Unfortunately, this failed to function due to the outdated server version at the client site.  So I ended up with PowerShell to launch the application…

I wrote 26 lines of code (see below) to check if the script had been run before; if it hadn’t, then it would create a flag.  Once it completed, it would check the flag, run the script, expect Imprivata to proxy the credentials, and the day was saved, right?!? 

 

# Create Windows Shell Object to allow for window to be minimized
$shell = New-Object -ComObject "Shell.Application"
# Create Registry Key Flag if it doesn’t already exist
if (!(test-path -path HKCU:SoftwareCUSTOMER -pathType container))
{
  New-Item -Path HKCU:Software -Name CUSTOMER
  New-ItemProperty "HKCU:SoftwareCUSTOMER" -Name "SynapseLaunched" -Value 0 -PropertyType "DWord"
}
#Check the value of Synapse Launched
if ((Get-ItemProperty 'hkCU:softwareCUSTOMER' -name SynapseLaunched | select -exp SynapseLaunched) -ne 1) 
{ 
  #launch Synapse then minimize all windows
  & 'C:Windowsexplorer.exe' "::{1FBD11EF-1260-11D1-87A7-444553540001}"
  start-sleep -s 2
  $shell.minimizeall() 
  #countdown from 2 seconds to allow app to connect to server
  Start-Sleep -s 2
  #kill Explorer.exe and relaunch
  $proc = Get-Process
  foreach ($objItm in $proc) 
  {
    If ($objItm.ProcessName -eq "explorer") 
    {
       kill $objItm.ID
    }
  }
  #Set SynapseLaunched Dword Value to 1
  Set-ItemProperty 'hkcu:softwareCUSTOMER' -name SynapseLaunched -Value 1  
}  

…Sadly, not so.  Imprivata at the client site was outdated and would not be available to be used for Windows 7 at the site for 2 months, causing an unacceptable delay in the project. 

Well, after the Imprivata approach failed for me, I needed to accomplish what I couldn’t do in Imprivata.  I started by thinking that perhaps I could launch an explorer process (this app is an explorer shell extension) as run as user with my username…  But no dice; the launching of explorer like that didn’t work because it would cause the files I needed to be created in a non-existent user profile, and would error out on the server.

So, I fell back to Windows VBS scripting’s SendKeys.  Since my script was already in PowerShell, and scripting in autoIT or VBS is something I rarely do, I experimented with creating a new Shell object.  Below is the code that I used for that:

 

#proxy Credentials
      $wshell = new-object -com wscript.shell
      $wshell.AppActivate("Windows Security")
      $wshell.sendkeys("{ENTER}")
      start-sleep -m 30
      $wshell.AppActivate("OneSign")
      $wshell.sendkeys("{ENTER}")
      start-sleep -m 30
      $wshell.AppActivate("Windows Security")
      $wshell.sendkeys("USERNAME")
      $wshell.sendkeys("{TAB}")
      $wshell.sendkeys("PASSWORD_OF_USER")
      start-sleep -m 30
      $wshell.sendkeys("{ENTER}") 

By utilizing $wshell = new-object -com wscript.shell, I was able to tap into .Net commands to interact with windows.  Now I could utilize some old VB Scripting code I had laying around from the past…

By utilizing $shell = New-Object -ComObject "Shell.Application", I was able to manipulate the Explorer.exe shell and minimize/maximize windows as I saw fit…

This was a very rewarding exercise.  Through this solution we (Coretek) were able to solve the client’s issues with the app, accommodate both teams (Desktop and PACs), simplify the end user experience, and best of all bring Windows 7 deployments back on schedule!

Send an Email from the Windows Command Prompt or Script, Pt II…

2017-07-27T00:01:03+00:00 November 14th, 2013|Uncategorized|

Following up on the earlier post, “Send an Email from the Windows Command Prompt or Script…

…While I’m somewhat picking up where I left off in Part 1, the situation in that earlier post had special requirements about how the email message had to be sent (controlled source, user interaction, etc.).  But what if you don’t have those requirements?  What if you simply want to send an email from a Windows workstation or Server? 

Well, in that case, simply use PowerShell.  Since version 2, PowerShell has included the Send-MailMessage cmdlet for relatively easy mail sending from almost any modern computer.

Recently, I was telling somebody how do use this method to send messages in a script, and demonstrating the input details such as specifying the SMTP relay server.  The person then asked me, “What if the SMTP server changes?”  Hmm…  Good point.   So I whipped up a few extra lines to work around that problem, and the person thought I should post it here.  Agreed!

Here is the script, put together as plainly as possible, with clearly named variables to help you understand what’s going on:

$MyRecipientEmailAddress = "Fake.Address@CoretekServices.com"
$MySenderEmailAddress = "JPavlov@YourLinuxGuy.com"
$MyRecipient = $MyRecipientEmailAddress.Split("@")
[0] $MyDestinationDomain = $MyRecipientEmailAddress.Split("@")[1] $MyMxRecords = Resolve-DnsName -Type MX -Name $MyDestinationDomain $MyMxRecord = $MyMxRecords[0].NameExchange $MyMessageSubject = "This is a test" $MyMessageBody = "This is the message. Thanks! - Jeremy" Send-MailMessage -To "$MyRecipientEmailAddress" -SmtpServer "$MyMxRecord" -Subject "$MyMessageSubject" -Body "$MyMessageBody" -From "$MySenderEmailAddress"

Remember, the trick is not really the standard options of the cmdlet, but grabbing the possibly-changing MX record for the relay.  This script will dynamically go and get the *current* first-listed MX record for the recipient, and just use that.

And I can almost hear you now, “…But Jeremy, aren’t you side-stepping the built-in fault-tolerance of the MX record?”  Yes, a bit; you can absolutely add a little more code to this and make it aware of the MX ranking, and roll through them and validate until successful.  Maybe I’ll do that in another post…

By the way, while it may not be obvious to you initially, note that I’m just specifying my recipient’s destination SMTP server as my -SmtpServer.  This *should* be fine in many/most cases.  The destination server should be glad to receive and forward the email to the end user that is a part of its own system.  However, some security protection may block this from happening, so be sure to know your destination first.  In my/our case, this was actually being used in an internal system to a friendly destination.  Your result may vary…

Now get out there and send those emails!


Fatal error: Uncaught exception 'GuzzleHttp\Exception\ClientException' with message 'Client error: `POST https://dc.services.visualstudio.com/v2/track` resulted in a `400 Invalid instrumentation key` response: {"itemsReceived":1,"itemsAccepted":0,"errors":[{"index":0,"statusCode":400,"message":"Invalid instrumentation key"}]} ' in /home/coretek/public_html/wp-content/plugins/application-insights/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 Stack trace: #0 /home/coretek/public_html/wp-content/plugins/application-insights/vendor/guzzlehttp/guzzle/src/Middleware.php(66): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response)) #1 /home/coretek/public_html/wp-content/plugins/application-insights/vendor/guzzlehttp/promises/src/Promise.php(203): GuzzleHttp\Middleware::GuzzleHttp\{closure}(Object(GuzzleHttp\Psr7\Response)) #2 /home/coretek/public_html/wp-content/plugins/application-insights/vendor/guzzlehttp/promises/src/Promise.php(156): GuzzleHttp\Promi in /home/coretek/public_html/wp-content/plugins/application-insights/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 113