Determining the location of Program Files using VBS - vba

What would a safe way of extracting the 'Program Files' directory location using VBS?. I would like to get the directory location from the environment as it will avoid localization issues as well as problems between different OS architectures (32/64 bit) and drive (C:\, D:\, etc:).
So far I came across an example given on MSDN yet I can get the script to work in VBS, every run just complains about different errors. Here is what they've got on an example script for .net to get the Sys32 folder.
' Sample for the Environment.GetFolderPath method
Imports System
Class Sample
Public Shared Sub Main()
Console.WriteLine()
Console.WriteLine("GetFolderPath: {0}", Environment.GetFolderPath(Environment.SpecialFolder.System))
End Sub 'Main
End Class 'Sample
'
'This example produces the following results:
'
'GetFolderPath: C:\WINNT\System32
'
As Helen mentioned, this is my script to determine the OS Architecture and depending on the outcome I wish to retrieve the respective 'Program Files' path
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & sPC & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
sSystemArchitecture = objOperatingSystem.OSArchitecture
Next

for vbs from How to get program files environment setting from VBScript
Set wshShell = CreateObject("WScript.Shell")
WScript.Echo wshShell.ExpandEnvironmentStrings("%PROGRAMFILES%")
if you are in vba
Sub GetMe()
Set wshShell = CreateObject("WScript.Shell")
MsgBox wshShell.ExpandEnvironmentStrings("%PROGRAMFILES%")
End Sub

Related

Filesystemobject Textstream, immediately disappears upon executing Textstream.Close (.vbs extension being created)

I have a situation that is really flummoxing me. Simple code I've used for years is failing in the weirdest way. I have a feeling the cause is related to either anti-virus junk or GPO, but, even those, I have seen them operate before on this scenario--but nothing like how I am seeing it now.
Note - this code has been working perfectly for several people, until one end-user got a new Surface laptop from I.T., purportedly for better compatibility with Teams and 365. ALL users (working, non-working) are on Windows 10.
Scenario:
I'm using Scripting.Filesystemobject
setting an object variable (Textstream intent), as fso.createtextfile
The filepath (name) I am creating is actually filename.vbs...At the moment this line executes, I can see the vbs file successfully in the folder
I use Textstream.Write to put some content in the file
I then use Textstream.Close (normally at this point you get a solid, stable, useable file). Immediately upon execution of the last line, Textstream.Close, the file DISAPPEARS from the folder-GONE.
The folder I'm writing to is the same as Start > Run > %appdata%
I've also tried this in Documents folder (Environ$("USERPROFILE") & "\My Documents") and get the exact same result
I've seen group policies and AV stuff that will prevent VBS from running, but that isn't my case--I've tested with this user, and she has no problem:
Creating a txt file in either of those folders
Manually creating a .vbs file in either of those folders
Even RUNNING the resulting vbs file in either folder
But somehow when I programmatically create .VBS in code, the second I close the textstream, the file is gone from the folder.
Any insight? The internet searches I did were void of all information on this scenario!! It would take me 2 weeks to open a ticket and get any help from I.T.
This is Excel VBA, but I highly doubt the problem has anything to do with Excel nor VBA...this is standard usage of windows scripting.filesystemobject:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'initiate full backup vbs script:
Dim ts As Object, fso As Object, strScriptText As String, strScriptPath As String
'populate our variable with the full text of the script: found on QLoader in this range:
strScriptText = ThisWorkbook.Worksheets("QLoader").Range("z_BackupScriptText").Value
'replace the text "placeholder" with this workbook's actual full path/name:
strScriptText = Replace(strScriptText, "placeholder", ThisWorkbook.FullName)
'fire up FSO:
Set fso = CreateObject("scripting.filesystemobject")
'determine the new VBS file's path
strScriptPath = Environ("AppData") & "\Backup_" & Format(Now, "yymmddhhmmss") & ".vbs"
'create our textstream object:
Set ts = fso.createtextfile(strScriptPath)
'write our script into it
ts.write strScriptText
'save and close it
ts.Close 'RIGHT HERE THE FILE DISAPPEARS FROM THE FOLDER ***********
'GO:
Shell "wscript " & strScriptPath, vbNormalFocus
End Sub
It does look like an antivirus thing...
If the issue is just the vbs extension though, you can use something like this:
Sub tester()
Dim ts As Object, fso As Object, strScriptText As String, strScriptPath As String
Set fso = CreateObject("scripting.filesystemobject")
strScriptPath = Environ("AppData") & "\Backup_" & Format(Now, "yymmddhhmmss") & ".txt"
Set ts = fso.createtextfile(strScriptPath)
ts.write "Msgbox ""Hello"""
ts.Close
'need to specify the script engine to use
Shell "wscript.exe /E:vbscript """ & strScriptPath & """ ", vbNormalFocus
End Sub

How to overcome CATIA.FileSelectionBox() error without setting "regserver option" as administrator?

The following code runs well if I have administrator permissions. But it doesn't work at all for a user.
Sub CATMain()
On Error Resume Next
Dim strpath As String
strpath = CATIA.FileSelectionBox("Select file", "*.xlsx",
CatFileSelectionModeOpen)
End Sub
I think CATIA.FileSelectionBox() works fine in CATScript so I was thinking in run a CATScript with Application.ExecuteScript(). When I try to do it another error pops up "Function or interface marked as restricted...". Can anyone give me an alternative method? Would be very much appreciated.
Ok, I found my answer. Thanks for letting me post my question in here. Next, I post a code that works just fine. The only thing that remains incomplete is that I can not add filters for types of files like *.CATParts or *.CATProducts in this code. But it works for me already.
Function SelectFile( )
' File Browser via HTA
' Author: Rudi Degrande, modifications by Denis St-Pierre and Rob van der
Woude
' Features: Works in Windows Vista and up (Should also work in XP).
' Fairly fast.
' All native code/controls (No 3rd party DLL/ XP DLL).
' Caveats: Cannot define default starting folder.
' Uses last folder used with MSHTA.EXE stored in Binary in
[HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32].
' Dialog title says "Choose file to upload".
' Source: https://social.technet.microsoft.com/Forums/scriptcenter/en-
US/a3b358e8-15ae-4ba3-bca5-ec349df65ef6/windows7-vbscript-open-file-dialog-
box-fakepath?forum=ITCG
Dim objExec, strMSHTA, wshShell
SelectFile = ""
' For use in HTAs as well as "plain" VBScript:
strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
& "<" & "script>FILE.click();new
ActiveXObject('Scripting.FileSystemObject')" _
&
".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" &
"/script>"""
' For use in "plain" VBScript only:
' strMSHTA = "mshta.exe ""about:<input type=file id=FILE>" _
' & "<script>FILE.click();new
ActiveXObject('Scripting.FileSystemObject')" _
' &
".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);
</script>"""
Set wshShell = CreateObject( "WScript.Shell" )
Set objExec = wshShell.Exec( strMSHTA )
SelectFile = objExec.StdOut.ReadLine( )
Set objExec = Nothing
Set wshShell = Nothing
End Function
Kind regards

VBA Excel SSO to SAP / runtime error 70 "access denied"

I spend hours finding the problem.
I want to start the SAP Logonpad with the ini file, that works fine.
Then after binding to the scripting object I want to open the connection to a specific System with connection = SapGui.OpenConnection("SID", True)
but always get runtime error 70 access denied.
I followed what others seem to do with vbs, for certain resons I can't do it with vbs and have to go with vba, so maybe there might be some difference that makes it fail?
Any advice would be highly appreciated.
Private Sub CommandButton1_Click()
Dim SapGui As Object
Dim saplogon As Object
Dim connection 'As Object
Set SapGui = GetObject("SAPGUI")
Dim Wshshell As Object
Set Wshshell = CreateObject("Wscript.Shell")
Wshshell.Run Chr(34) & ("C:\Program Files\SAPPC\FrontEnd\SAPgui
\saplogon.exe") & Chr(34) & " " & "/INI_FILE" & "=" & Chr(34) &
"\\longpathtoini\appl\Sap\saplogon\int\saplogon.ini" & Chr(34)
Do Until Wshshell.AppActivate("SAP Logon")
Application.Wait Now + TimeValue("0:00:01")
Loop
Set Wshell = Nothing
Set saplogon = SapGui.GetScriptingEngine
connection = SapGui.OpenConnection("SID", True)
Set SapGui = Nothing
Set saplogon = Nothing
Set connection = Nothing
End Sub
Check whether user scripting is allowed for the particular system (transaction RZ11, parameter sapgui/user_scripting). Also be aware that for some versions, you'll apparently need to specify the SAP Logon entry text instead of the SID.
Thanks to vwegert.
I surely knew about scripting needs to be enabled on the servers.
Which is, but at the moment I read his answer I remembered that in my SAP GUI settings the checkbox for "Warn if a script tries to connect" was enabled.
Disabeling that options did lead to success.
The above code works perfectly.

Checking Print Spooler status (running or not)

I need to detect whether the Print Spooler service is running. I can find various resources for VB.NET (e.g., using ServiceProcess.ServiceController to actually manipulate the service), but nothing for VB6.
Is there any way to check whether the Print Spooler is running in VB6? And ideally start it, but I can survive without that.
We use wmi in VBA/VB6/VBScript and command prompt.
This lists processes
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
msgbox objitem.name & " PID=" & objItem.ProcessID & " SessionID=" & objitem.sessionid
' objitem.terminate
Next
This is typed an command prompt.
wmic process get
You'll see you can get VBS methods/properties by using wmic help
wmic /?
wmic process /?
wmic process get /?
So wmic service get caption,status
so
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Service")
For Each objItem in colItems
msgbox objitem.name & " " & objitem.status
Next
Since there's only one Print Spooler, you can query the Win32_Service class for the single instance. Then, check the Started property to determine if it's started/running:
Set objSpooler = GetObject("winmgmts:root\cimv2:Win32_Service.Name='Spooler'")
If objSpooler.Started Then
MsgBox "Print Spooler is running."
Else
MsgBox "Print Spooler is NOT running."
End If
Both answers already posted are good (and will solve the problem) but I just wanted to answer my own question to incorporate an answer given elsewhere (By user Bonnie West over at VBForums.com), as it gives an additional approach and is probably useful for anyone else who finds this question:
Option Explicit 'In a standard Module
Private Sub Main()
With CreateObject("Shell.Application") 'Or New Shell if Microsoft Shell Controls And Automation is referenced
If .IsServiceRunning("Spooler") Then
.ServiceStop "Spooler", False
Else
.ServiceStart "Spooler", False
End If
End With
End Sub
Source

vbscript permission denied 800a0046 network

I made a script that copying a file to a certain location.
I add the .vbs to taskschd.msc scheduled for make a .pst backup
but I get error message
Line: 91
Char: 7
Error: Permission denied
Code: 800A0046
Source: Microsoft VBScript runtime error
<pre>
'Set the amount of pst-files you want to copy. Start counting at 0!
ReDim pst(1)
'Define the location of each pst-file to backup. Increase the counter!
pst(0) = "C:\Users\daniel.elmnas.TT\Documents\Outlook Files\de#teknotrans.se.pst"
pst(1) = "C:\Users\daniel.elmnas.TT\Documents\Outlook Files\de.pst"
'Define your backup location
BackupPath = "\\ttad-1\Gemensam\Outlook_Backup\Daniel Elmnäs"
'Keep old backups? TRUE/FALSE
KeepHistory = FALSE
'Maximum time in milliseconds for Outlook to close on its own
delay = 30000 'It is not recommended to set this below 8000
'Start Outlook again afterwards? TRUE/FALSE
start = TRUE
'===================STOP MODIFY====================================
'Close Outlook
Call CloseOutlook(delay)
'Outlook is closed, so we can start the backup
Call BackupPST(pst, BackupPath, KeepHistory)
'Open Outlook again when desired.
If start = TRUE Then
Call OpenOutlook()
End If
Sub CloseOutlook(delay)
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
'If Outlook is running, let it quit on its own.
For Each Process in objWMIService.InstancesOf("Win32_Process")
If StrComp(Process.Name,"OUTLOOK.EXE",vbTextCompare) = 0 Then
Set objOutlook = CreateObject("Outlook.Application")
objOutlook.Quit
WScript.Sleep delay
Exit For
End If
Next
'Make sure Outlook is closed and otherwise force it.
Set colProcessList = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = 'Outlook.exe'")
For Each objProcess in colProcessList
objProcess.Terminate()
Next
Set objWMIService = Nothing
Set objOutlook = Nothing
set colProcessList = Nothing
End Sub
Sub BackupPST(pst, BackupPath, KeepHistory)
Set fso = CreateObject("Scripting.FileSystemObject")
If KeepHistory = True Then
ArchiveFolder = Year(Now) & "-" & Month(Now) & "-" & Day(Now)
BackupPath = BackupPath & ArchiveFolder & "\"
End If
If fso.FolderExists(BackupPath) = False Then
fso.CreateFolder BackupPath
End If
For Each pstPath in pst
If fso.FileExists(pstPath) Then
fso.CopyFile pstPath, BackupPath, True
End If
Next
Set fso = Nothing
End Sub
Sub OpenOutlook()
Set objShell = CreateObject("WScript.Shell")
objShell.Run "Outlook.exe"
End Sub
</pre>
Could someone help me to solve this?
Thank you in advance
Seems like you schedule the script.
You need to start the task with a user that executes the script which has rights on the PST file, as well as on the path where you store the backup. Running it with the system account won't be enough.
There are better ways to backup PST files also, I use a Ruby script to synchronise a local copy with a backup copy, is runs on PST's more than 10GB big without problem, might be a problem if you would do it with a copy like this.
You need to backup the copy on a backup medium also because when the PST has errors (and all big PST have) you copy the errors to the backup and could lose both.
Also, you do the following
BackupPath = "\\ttad-1\Gemensam\Outlook_Backup\Daniel Elmnäs"
...
BackupPath = BackupPath & ArchiveFolder & "\"
Where is the \ between the two first variables ?
EDITED: Change the permissions of the folder.
In windows explorer, navigate to the folder where the PST file is located.
In the left pane of windows explorer, right click on the folder where the PST file is located, select "Properties".
Select the "Security" tab
Click the button "Edit" to change permissions.
Click "Add"
In the object names to select box, enter "everyone" (no quotes).
Click "Check Names", everyone should become capitalized and underlined.
Click "Ok"
Select "Everyone" from the list of Groups or user names.
In the "Permissions for Everyone" list, make sure "Read & Execute, List folder contents and Read, in the allow column are checked, click "Apply"
Click Ok.
NOTE: By doing this, anyone who has access to this computer can access the folder. You might consider only adding your login to the computer to the list of Groups or usernames instead of Everyone. You may have to repeat the above steps on the PST file(s) in question.
Original Post:
I ran the script here, testing for various issues and it ran without problems. At this point I believe the issue is rights and permissions to either the source or destination folder (or the files you are backing up). By default, the user's themselves don't have access to Outlooks data files. You would need to add "read" permissions to the files in question (PST,OST, and so on) or the full folder.
In reality, just backing up the PST files isn't enough to restore an Outlook configuration; you would need all of the files.
You can Try this:
'===================================================================
'Description: VBS script to backup your pst-files.
'
'Comment: Before executing the vbs-file, set the location of outlook
' folder you want to backup and
' the backup location (this can also be a network path).
' See the URL below for more configuration instructions and
' how to create a Scheduled Task for it.
'
' Original author : Robert Sparnaaij
' Modified: Fred Kerber
' version: 1.1
' website: http://www.howto-outlook.com/downloads/backupscript.htm
' Changes:
' Changed var types; changed to backup full folder and not just pst files.
'===================================================================
'===================BEGIN MODIFY====================================
'Define the folder location of Outlook's data files.
sOutlookDataPath = "C:\Users\FKerber.CORP\AppData\Local\Microsoft\Outlook\"
'Define your backup location
sBackupPath = "E:\Outlook Backup\"
'Keep old backups? TRUE/FALSE
bKeepHistory = TRUE
'Maximum time in milliseconds for Outlook to close on its own
iDelay = 30000 'It is not recommended to set this below 8000
'Start Outlook again afterwards? TRUE/FALSE
bStart = True
'===================STOP MODIFY====================================
'Close Outlook
Call CloseOutlook(iDelay)
'Outlook is closed, so we can start the backup
Call BackupOutlook(sOutlookDataPath, sBackupPath, bKeepHistory)
'Open Outlook again when desired.
If bStart = TRUE Then
Call OpenOutlook()
End If
Sub CloseOutlook(iDelay)
Set objWMIService = GetObject("winmgmts:" &_
{impersonationLevel= impersonate}!\\.\root\cimv2")
'If Outlook is running, let it quit on its own.
For Each oProcess in objWMIService.InstancesOf("Win32_Process")
If StrComp(oProcess.Name,"OUTLOOK.EXE",vbTextCompare) = 0 Then
Set objOutlook = CreateObject("Outlook.Application")
objOutlook.Quit
WScript.Sleep delay
Exit For
End If
Next
'Make sure Outlook is closed and otherwise force it.
Set colProcessList = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = 'Outlook.exe'")
For Each objProcess in colProcessList
objProcess.Terminate()
Next
Set objWMIService = Nothing
Set objOutlook = Nothing
Set colProcessList = Nothing
End Sub
Sub BackupOutlook(sOutlook, sBackupPath, bKeepHistory)
Set ofso = CreateObject("Scripting.FileSystemObject")
If bKeepHistory = True Then
sArchiveFolder = Year(Now) & "-" & Month(Now) & "-" & Day(Now)
sBackupPath = sBackupPath & sArchiveFolder & "\"
Else
For Each oFile In ofso.GetFolder(sBackupPath).Files
ofso.DeleteFile oFile.Path, True
Next
End If
If ofso.FolderExists(sBackupPath) = False Then
ofso.CreateFolder sBackupPath
End If
For Each oFile In ofso.GetFolder(sOutlook).Files
If ofso.FileExists(oFile.Path) Then
ofso.CopyFile oFile.Path, sBackupPath, True
End If
Next
Set ofso = Nothing
End Sub
Sub OpenOutlook()
Set objShell = CreateObject("WScript.Shell")
objShell.Run "Outlook.exe"
End Sub
I had a similar problem trying to delete files with VBS. I assume that as with my case: The source of the problem is that the script is trying to perform some operation on a file or folder that has a Read-only Attribute. To solve this manually you could left click -> properties -> unclick the Read-Only Attribute then the file/folder should be copied by the script. To solve the problem with VBS: I make the assumption that file/folder is set to Read-Only because there is a programme currently using them.
One: we can just skip files/folders set to read-only this time and hope to get them next time the script runs. For this we first check if file/folder is read-only (I got this from here: https://social.technet.microsoft.com/Forums/ie/en-US/7382d452-1ef9-404a-8874-48d38fcfe911/vbscript-verify-if-a-file-is-readonly?forum=ITCG), if not then we perform the copy operation.
Sub BackupPST(pst, BackupPath, KeepHistory)
'........
For Each pstPath in pst
If fso.FileExists(pstPath) Then
If not (fso.GetFile(pstPath).Attributes AND 1) Then 'if item is not read-only
fso.CopyFile pstPath, BackupPath, True
End If
End If
Next
Set fso = Nothing
End SubSub
Two: At the very least this should prevent you from getting the error. But if the script never moves the files even after running a number of times then chances are that the files (you are trying to move) are always in read only and you should change Attribute of the file (you are trying to move) in your script before calling the copy function, see how to do that here: https://devblogs.microsoft.com/scripting/how-can-i-change-a-read-only-file-to-a-read-write-file/