vb script simulate keystroke when not logged in - vbscript

I really don't know much about VB script, and I could use some help with this little problem.
I'm trying send an email once a certain script is run every morning (a scheduled task). Now, our email server is configured to prevent sending automated emails - a feature I generally appreciate - and so I need to simulate a keystroke to acknowledge a warning box and actually send the email.
Here's the script I have so far:
Sub SendEmail_Outlook()
Set WshShell = WScript.CreateObject("WScript.Shell")
Set ol=CreateObject("Outlook.Application")
Set Mail=ol.CreateItem(0)
Mail.to= "X#xyz.com"
Mail.Subject = "Subject"
Mail.HTMLBody = "Body"
Mail.Display
WScript.Sleep 1000
WshShell.SendKeys "%s"
Set Mail = Nothing
Set ol = Nothing
End Sub
SendEmail_Outlook
The script works like a charm, but only if I'm logged in. If I'm not logged in, the email draft is prepared, the window is activated, but the email is not actually sent. I'm assuming it's because the simulated keystroke does not work if no one's logged in?
So, the question is: is there a way to "tweak" this script to make it run even when no one's logged in?
Many thanks, help would be appreciated!
Philipp

Did you check the vbscript [info] section? It explains how cscript.exe can execute vbscript while the user is not logged on.
"Note: Scheduled VBScript tasks succeed under Cscript.exe due to running the script as a console application rather than a windows application. Computer/Domain policies limit activation of windows applications while no user is logged on."
Edit:
Activate the sending of email over the .Send property rather than using the sendkeys method.
Sub SendEmail_Outlook()
Set WshShell = WScript.CreateObject("WScript.Shell")
Set ol=CreateObject("Outlook.Application")
Set Mail=ol.CreateItem(0)
Mail.to= "X#xyz.com"
Mail.Subject = "Subject"
Mail.HTMLBody = "Body"
Mail.Display
WScript.Sleep 1000
'-----------
Mail.Send
'-----------
Set Mail = Nothing
Set ol = Nothing
End Sub
SendEmail_Outlook
Further information on automating emails directly too the outlook application can be referenced here: Link

With the help of a colleague, I think I found the answer - at least it's an option I've implemented and it seems to run successfully so far. As this may be of interest to others as well, there's what we have done:
Download and install "Outlook Redemption" here: http://www.dimastr.com/redemption/home.htm. No admin rights required.
Use the following script:
Sub SendEmail_Outlook()
Set WshShell = WScript.CreateObject("WScript.Shell")
Set oApp=CreateObject("Outlook.Application")
Set NS = oApp.GetNamespace("MAPI")
NS.Logon
Set SafeItem = CreateObject("Redemption.SafeMailItem")
Set oMailItem = oApp.CreateItem(0)
SafeItem.Item = oMailItem
SafeItem.To = "x#yz.com"
SafeItem.Subject = "Subject"
SafeItem.BodyFormat = 2
SafeItem.HTMLBody = "Body"
SafeItem.Send
SafeItem = Nothing
Set oMailItem = Nothing
Set NS = Nothing
Set oApp = Nothing
End Sub
SendEmail_Outlook
As indicated, the script has been running smoothly, despite getting an error at the end, saying that:
VBScript runtime error: Object variable not set: 'SafeItem'
But, the email arrives, so the error doesn't really bother me... ;-)

Related

Crash when using SafeMailItem (fault in mso20win32client.dll)

We use Redemption since many years. Since few days many of our clients have issues when they use our plugin for Outlook. We changed nothing in our app.
I did some traces and found that the line Set CourielOutlook = New Redemption.SafeMailItem makes the app to crash. Events viewer show that the fault is in mso20win32client.dll.
I tried to find the problem by create a simple app doing the same thing and there is no problem with this one!!?
I found that if I rename the original app with a new name (AddinOutlook.exe to AddinOutlook2.exe), the app doesn't crash anymore!
If I rename my simple app to AddinOutlook.exe, it crashes!
I tried many things in Outlook (deleting and recreating the profile, deleting and recreating the account, uninstall and reinstall Office 365). The problem still there.
After deleting and recreating the profile, it works the first time, but after that never (except if I rename the exe).
Any idea?
Here is my simple test app:
Dim Outlook As Outlook.Application
Dim Item As Object
Dim Namespace As Object
Dim CourielOutlook As Object 'Redemption.SafeMailItem
Set Outlook = New Outlook.Application
If Not Outlook Is Nothing Then
On Error Resume Next
Err.Clear
Set Namespace = Outlook.GetNamespace("MAPI")
If Err.Number <> 0 Then
Call Namespace.Logon(vbNullString, vbNullString, False)
End If
If Err.Number = 0 Then
If TypeName(Outlook.ActiveWindow) = "Inspector" Then
Call AjouterElement(Outlook.ActiveInspector.CurrentItem)
Set CourielOutlook = New Redemption.SafeMailItem
CourielOutlook.Item = Outlook.ActiveInspector.CurrentItem
'...
ElseIf TypeName(Outlook.ActiveWindow) = "Explorer" Then
For Each Item In Outlook.ActiveExplorer.Selection
Set CourielOutlook = New Redemption.SafeMailItem
CourielOutlook.Item = Item
'...
Next
End If
End If
End If
Set Outlook = Nothing

How to login in Office 365 from VBScript and browse through sharepoint with pascal script(?)

I'm packing an Access application, This is connecting with a Sharepoint site. I'm using Inno Setup (With Pascal Scripts) for create an install package. So,
I found this code for do something similar to that I want, when I run the code seems work fine: Open the browser, goes to Office 365, puts information (account and password), but just in the moment when open the cmd and after few seconds, all closes without finish the process.
On Error Resume Next
Const PAGE_LOADED = 4
Set objIE = CreateObject("InternetExplorer.Application.1")
Call objIE.Navigate("https://yourdomain.sharepoint.com")
objIE.Visible = True
Do Until objIE.ReadyState = PAGE_LOADED : Call WScript.Sleep(500) : Loop
objIE.Document.all.Login.Value = "username#yourdomain.com"
objIE.Document.all.Passwd.Value = "office365password"
objIE.Document.all.persist.checked=True
'The "Submit" button needs to be "clicked" twice in order to sign the user in
' * It appears that some javascript needs to take place behind the scenes to properly initiate the logon
Call objIE.Document.getElementById("cred_sign_in_button").click
Call objIE.Document.getElementById("cred_sign_in_button").click
WScript.Sleep(4000)
Do Until objIE.ReadyState = PAGE_LOADED : Call WScript.Sleep(500) : Loop
Set wShell=CreateObject("WScript.Shell")
NetCommand="net.exe use p: ""https://yourcompany.sharepoint.com/Library 1"" /user:username#yourdomain.com office365password"
wShell.Run "cmd.exe /C " & NetCommand, 1, True
Set wShell=Nothing
objIE.quit
Set objIE = Nothing
Seems to maybe can be here:
Set wShell=CreateObject("WScript.Shell")
NetCommand="net.exe use p: ""https://yourcompany.sharepoint.com/Library 1"" /user:username#yourdomain.com office365password"
wShell.Run "cmd.exe /C " & NetCommand, 1, True
My final aim is do the all process of login in the backstage (for code), create the connexion with 365 via (VBScript (?)), providing the credentials in the script, thereupon go a list in sharepoint site, title: (Serial Numbers(?)) where I Have a list with several numbers and checkboxes for to mark true in every install and avoid use the same number two times.
Thanks for advance!

Get list of ALM project AND domains names in VBScript (QC11 OTA)

I am trying to list QC11 project and domain name in combo box on form load() but I am getting error object required,code I am using:
Dim tdc As New TDAPIOLELib.TDConnection
Dim projectList As Customization
Dim Project As Customization
Dim Domain As Customization
Set tdc = CreateObject("TDApiOle80.TDConnection")
tdc.InitConnectionEx "https://xyz/omu"
For Each Domain In TheTDConnection.DomainsList
Set projectList = tdc.GetAllVisibleProjectDescriptors
For Each Project In projectList
ComboBox1.AddItem (Project.Name)
ComboBox2.AddItem (Project.DomainName)
Next Project
Next Domain
If that's really the code you are using, then for a start this line is probably generating an error:
For Each Domain In TheTDConnection.DomainsList
Based on the rest of your code "TheTDConnection" should be "tdc":
For Each Domain In tdc.DomainsList
Oh, and to be doing this you should almost certainly be logged in first by calling tdc.Login... rather than just connected to the server.
On a related note, the DomainsList property is deprecated. I think you can just loop through the List of ProjectDescriptor objects returned by GetAllVisibleProjectDescriptors since that covers all projects under all domains that the current logged on user has access to.
Edit: this is a complete solution based on the original question. Here's working tested code that will cycle through the domains/projects that the provided user has access to. This assumes you have the QC/ALM Connectivity add-in installed (required).
If you are running this piece of VBScript on a 64 bit machine you need to run it using the 32bit version of wscript.exe: C:\Windows\SysWOW64\wscript.exe "c:\somewhere\myscript.vbs"
msgbox "Creating connection object"
Dim tdc
Set tdc = CreateObject("TDApiOle80.TDConnection")
msgbox "Connecting to QC/ALM"
tdc.InitConnectionEx "http://<yourServer>/qcbin/"
msgbox "Logging in"
tdc.Login "<username>", "<password>"
Dim projDesc
msgbox "Getting project descriptors"
Set projectDescriptors = tdc.GetAllVisibleProjectDescriptors
For Each desc In projectDescriptors
msgbox desc.DomainName & "\" & desc.Name
Next
msgbox "Logging out"
tdc.Logout
msgbox "Disconnecting"
tdc.Disconnect
msgbox "Releasing connection"
tdc.ReleaseConnection
Edit 2:
If you want to parse the resulting XML from sa.GetAllDomains into a list of ALL domain\project items on the server you can do this (This is VBScript since the original question & tag still mention it, and has been tested):
Set objDoc = CreateObject("MSXML.DOMDocument")
objDoc.Load "C:\yourXmlFile.xml"
Set objRoot = objDoc.documentElement
For Each domain in objRoot.selectNodes("TDXItem")
For Each project in domain.selectNodes("PROJECTS_LIST/TDXItem")
msgbox domain.selectSingleNode("DOMAIN_NAME").text & "\" & project.selectSingleNode("PROJECT_NAME").text
Next
Next

How do I get Active Directory's LDAP server url using windows API?

I've been looking for a way to get Active Directory's LDAP server url from code running as domain user. The code needs to work correctly in situation with disjoint namespace, if possible. It's unmanaged code so any .NET solutions are not an option unfortunately.
For some reason serverless binding doesn't seem to be working in this case with ADO query returning unhelpful One or more errors occurred during processing of command error when using LDAP://DC=mycompany,DC=local (that's the value of the defaultNamingContext attribute of rootDSE object).
Using the LOGONSERVER and USERDNSDOMAIN environment variables doesn't appear to be an option either because the code also needs to be able to run under the SYSTEM account and there are no such variables there.
Any ideas or hints or specific RTFM advice will be much appreciated.
Update: The DNSHostName attribute of rootDSE seems to be what I need.
I use this Visual Basic Script (VBS). Save the code as .vbs file and use ANSI charset. This script is old, but this can guide you to a better solution.
Set cn = CreateObject("ADODB.Connection")
Set cmd= CreateObject("ADODB.Command")
cn.Provider = "ADsDSOObject;"
cn.open
cmd.ActiveConnection = cn
' Root DSE required to get the default configuration naming context to
' be used as the root of the seach
set objRootDSE = getobject("LDAP://RootDSE")
' Construct the LDAP query that will find all the domain controllers
' in the domain
ldapQuery = "<LDAP://" & objRootDSE.Get("ConfigurationNamingContext") & _
">;((objectClass=nTDSDSA));ADsPath;subtree"
cmd.CommandText = ldapQuery
cmd.Properties("Page Size") = 1000
Set rs = cmd.Execute
do while rs.EOF <> True and rs.BOF <> True
' Bind to the domain controller computer object
' (This is the parent object of the result from the query)
set objDC = getobject(getobject(rs(0)).Parent)
wscript.echo objDC.dNSHostName
rs.MoveNext
Loop
cn.close
The DNSHostName attribute of rootDSE seems to be what I need.

vbscript a condition statement based off of a Membership group In Active directory

I use vbscript to autolaunch internet explorer windows through a client folder in our environment. we just introduced a new system that manages our logons and the autolaunch is based off a computer policy in that system. it can only run off of a specific computer policy. So my idea was to add a conditional statement that said. If one user logs query ad if they are apart of this group launch this window, else launch the windows we have already been launching. I have the code to create and launch websites through vbscipt, what i am looking for is the script to query ad and based on group member ship launch that windows else launch the normal ones. the system is called imprivata.
This script might do what you want:
strGroup = "GroupName"
Set objNetwork = CreateObject("WScript.Network")
strDomain = objNetwork.UserDomain
strUser = objNetwork.UserName
Set objUser = GetObject("WinNT://" & strDomain & "/" & strUser)
Dim found
found = false
For Each objGroup In objUser.Groups
If StrComp(objGroup.Name, strGroup, 1) = 0 Then
found = true
Exit For
End If
Next
' use the found variable to decide what to do
Just change "GroupName to the group you're looking for.
However, Morbo's comment is important, since if you care about indirect memberships, you'd have to recurse through all the groups found to see if any of them, or the groups they're a member of etc, are a member of the group you care about.

Resources