Why are some Windows registry values readable by VBScript but not VBA? - vba

I'm trying to read a registry value using VBScript and VBA.
This works in VBScript but in VBA it returns the read error below:
Set objshell = CreateObject("WScript.Shell")
ID = objshell.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID")
And I noted that I can't actually see the value in the regedit app with/without running as administrator. Is this something to do with registry virtualisation?
UPDATED BASED ON REGISTRY REDIRECTION COMMENTS
Since the code above runs on 64 bit Office, it should be possible to craft something like this, but the 32 bit part still throws an error.
#If Win64 Then ' 64 bit Office
Debug.Print CreateObject("WScript.Shell").RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID")
#Else ' 32 bit Office
Debug.Print CreateObject("WScript.Shell").RegRead("HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\ProductID")
#End If

Related

Set objBAPIControl = CreateObject("SAP.Functions")

At line Set objBAPIControl = CreateObject("SAP.Functions") I face the runtime error 429
ActiveX component can't create object.
The script was initially running in a 32 bit system now it is upgraded to 64 bit.
This is the logon script:
Private Sub SAP_Initialize_Objects()
Set objBAPIControl = CreateObject("SAP.Functions")
Set sapConnection = objBAPIControl.Connection
bln_SAP_Objects_Initiated = True
End Sub
If sapConnection.IsConnected <> 1 Then
If you use MS Office 64 bits (I say "if" because in a 64 bits OS, MS Office 32 bits can be used), and SAP GUI 32 bits, then it won't work by default.
There are 3 possible solutions/workarounds:
Install SAP GUI for Windows 7.70 which is the first version to be 64 bits
Use the feature "DLL Surrogate" by changing the registry -> See this stack overflow answer
Convert VBA into VBScript that you run in 32 bits (outside your MS Office application)
Dim <var> As <type> in VBA ▶ Dim <var> in VBScript
etc. (search Web for differences, e.g. this (non-exhaustive) Microsoft document)

Telling VBA to look at 64-bit registry view

I want to assign an ArrayList to a variable.
Sub Create_ArrayList()
Dim arrL As Object
'Creating an ArrayList, option 1 - fails
Set arrL = CreateObject("System.Collections.ArrayList")
'Creating an ArrayList, option 2 - fails
Set arrL = GetObject("New:{6896B49D-7AFB-34DC-934E-5ADD38EEEE39}")
End Sub
Both options fail :
Run-time error '-2146232576 (80131700)':
Automation error
I found that the CLSID exists in the registry in HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
The Office is 32-bit and Windows is 64-bit. I am not familiar with the registry, but it seems from what I have read, that 32-bit Office is trying to find ArrayList in some 32-bit Windows location (view), while it actually is in 64-bit location. Can it be the case? How to make the application get ArrayList from the correct location?
It seems, to access an alternative registry view, I should somehow use the flag KEY_WOW64_64KEY (value 0x0100), but the examples that I found are too big to comprehend (eg1, eg2). I don't want to edit registry data, I only want to tell VBA that I am using 64-bit Windows, so the object that I need is to be found somewhere else than it expects.

Conditional mechanism in Word VBA

I have a .dot file with one line of code that must be executed in a Microsoft Word macro if and only if the version of Word 2003 or greater is installed, otherwise it shuold be ignored. I tried to implement it like this, hoping that Visual Basic for Word compiles a line only if it needs to execute it. The code in question is the following (Word 2003 is 11.0)
If Val(Application.Version) >= 11 Then
ActiveWindow.View.ReadingLayout = False
End If
I still want that the .dot file with the macro is usable in earlier versions of Microsoft Word, such as Microsoft Word 2000.
However, if I try to run the .dot file, it fails on Word 2000 with a compile error because ActiveWindow.View.ReadingLayout is not a valid method in Word 2000. That is, even when the line will never be executed on Word 2000 because Application.Value will be 9.0, Word still tries to compile that line.
Is there any way in Visual Basic for Word to add compiler directives so that some code is not compiled depending on the Word version?
We ended up implementing it with late binding, which turned out to be a very small tweak:
If Val(Application.Version) >= 11 Then
Dim obj As Object
Set obj = GetObject(, "Word.Application")
obj.ActiveWindow.View.ReadingLayout = False
End If
Their are two tricks to get it working:
1)
Add a module for functions that work only in specific office version and add your subroutines to it.
2)
In places where you have to call your functions, add a test for the specific Office Version and then call your subroutine with Application.Run
The original Module would have:
If Val(Application.Version) >= 11 Then
Application.Run "office11module.disableReadingLayout"
End If
And your specific Module office11module would have
Public Sub disableReadingLayout()
ActiveWindow.View.ReadingLayout = False
End Sub
This works because Word is not compiling the office11module until it is needed, and we make sure through the Application.Run call that Word does not know that we need it before runtime.
Our Word VBA Products require a Digital Signature.
We utilize MS Office 2000 as a base development application in order to be as backward compatible as possible with some of our clients.
We utilized the solution provided by jonas_jonas (Jan 16 '14 at 17:59) for years while using Word 2000 on Windows XP development platforms.
However - after upgrading to Windows 7 Pro development platforms, the solution no longer worked, giving us "Disk full" errors when attempting to save the Word files after having digitally signed them.
We then tried, and successfully used, the answer (above) provided by Pep (Jan 18 '14 at 23:23) which works when you need to Digitally Sign the Word file.
We figured the "disk full" error was a result of the attempt to compile the project before saving.
If Val(Application.Version) >= 11 Then
Dim obj As Object
Set obj = GetObject(, "Word.Application")
obj.ActiveWindow.View.ReadingLayout = False
End If

Cannot instanciate a NotesUIWorkspace from VBA (Word)

The source situation: I have an Notes Application which uses MS Office 2000 under Windows XP. The new situation has to be MS Office 2010 under Windows 7. IBM Notes is 8.5.3FP3.
The old one uses a VBA template to communicate with Notes which works properly. At one time a Notes.NotesUiWorkSpace object is created to open a document, navigate to a richtext item, select all the content (formatted) and copy to the clipboard. Then the clipboard content ist pasted into the Word document via VBA. That works fine.
The same code in the second environment doesn't work anymore. I noticed that the Notes.NotesUIWorkSpace object cannot be instanciated in VBA. No errors, no hints. Only the runtime error when I reference the workspace-object later.
Here is a code excerpt:
' this is a profile document which is filled correctly
Call prof.Save(True, True)
Call prof.replaceItemValue("Form", "Profile")
' setting up the ui
dim WS as Object
set WS = CreateObject("Notes.NotesUiWorkSpace")
Set uiprof = WS.EditDocument(True, prof)
' Set uiprof = WS.currentDocument
If uiprof.editMode Then Call uiprof.gotofield("RT")
Call uiprof.SelectAll
Call uiprof.Copy
Call uiprof.Close
' later on the clipboard will be pasted into the word document
Any ideas what could be the cause here? I am setting up an environment with XP, MS Office 2010 and Notes tonight to check it out that it is not caused by Windows 7.
If the Windows 7 machine is 64 bit, take a look at the answers here. Note that those refer to the COM classes (lotus.), and you are using the OLE classes (notes.), but I believe the 64/32 bit issue applies to both.

How to open specific version of Word 2007/2010 in Excel

I have both Word 2007 and 2010 installed. I need to open Word from within Excel but I need to specify which version I need to open within VBA.
I've tried late binding
Dim wordApp2007 As Object
Dim wordApp2010 As Object
Set wordApp2007 = CreateObject("Word.Application.12")
wordApp2007.Visible = True
Set wordApp2010 = CreateObject("Word.Application.14")
wordApp2010.Visible = True
but both open Word 2010
I've also tried early binding by using
Dim wordApp As Word.Application
Set wordApp2007 = New Word.Application
wordApp2007.Visible = True
and setting references to the Word 12.0 object model but this still opens Word 2010
If I register each version of Word using
"C:\Program Files\Microsoft Office\Office12\WINWORD.EXE" /regserver
"C:\Program Files\Microsoft Office\Office14\WINWORD.EXE" /regserver
then the version registered opens but then I can't open open the non-registered.
Can anyone help and show me how to open a specific version of Word within Excel using VBA?
Thank you
Edit: Example code....
Option Explicit
Dim wordApp2007 As Word.Application
Sub Word_InfoEarly()
'early binding
Set wordApp2007 = New Word.Application
wordApp2007.Visible = True
'other Stuff
Stop
wordApp2007.Quit
Set wordApp2007 = Nothing
End Sub
Sub Word_InfoLate()
Dim wordApp2007 As Object
Dim wordApp2010 As Object
Set wordApp2007 = CreateObject("Word.Application.12")
wordApp2007.Visible = True
Set wordApp2010 = CreateObject("Word.Application.14")
wordApp2010.Visible = True
'other Stuff
Stop
wordApp2007.Quit
Set wordApp2007 = Nothing
wordApp2010.Quit
Set wordApp2010 = Nothing
End Sub
This is a work around:
TaskID = Shell("C:\Program Files\Microsoft Office\Office12\WINWORD.EXE",vbHide) '2007
'TaskID = Shell("C:\Program Files\Microsoft Office\Office14\WINWORD.EXE",vbHide) '2010
GetObject(,"Word.Application")
You would also need to test if a previous version of word is open, or use something other than a basic GetObject to activate the window, else there's no guarantees that it will get the right version.
The other way would be to pass the document name in the Shell command, and then GetObject could be called with the document name
This may further explain why the code works some times and not others.
My observation on the situation of the command
'Set wordAppxxxx = CreateObject("Word.Application.xx")'
working or not on your computer is that it is a function of the latest update you get from Microsoft.
Why I believe this:
I have an application that converts a text file to a Word document for backwards compatibility with some legacy apps. The best plan includes using a version of Word similar to the version the legacy apps were designed with/to. As a result, I searched on how to invoke a legacy version of Word as opposed to the default offering on my computer which is Word 2010.
The solution noted in this discussion chain provided the answer to my question. (Thank you Stack Overflow contributors!) I wanted to use Word XP, so I looked at my directories and observed that Word XP (aka Word 2002) is a member of Office 10, so I created the command
'Set wordApp2002 = CreateObject("Word.Application.10")'
and my program launched Word 2002 and the world was a happy place.
Over the weekened, I had an update to my computer. I control the updates via an app which gives me control over when updates occur such that I can observe changes to my configuration. This morning (9/30/13) I turned on a computer that had a Word update. I did not know this until after I had made one run of my app from last week. The app ran fine and invoked Word 2002 as expected.
But then I got the banner page informing me of a Word 2010 update that was installing itself.
Afterwards, I ran the app that worked so well for me last week and once today. Now, after the Word update (immediately after!), the same code now launches Word 2010 despite the fact that the command line invoking Word 2002 has not changed.
This appears strong evidence that a Microsoft update tweaked the settings that previously allowed the VB code to work as expected. This might be a good item to bring to Microsoft's attention so see if we can get this item stabilized in subsequent update packages to allow consistent behavior in future releases.
I hope this is helpful,
JeffK
I wasted half a day on this, and want to help prevent others doing the same! I'm running Windows 7 and Office 2013 and 2010 on the same laptop. I wanted to get Access VBA to open up an old version of Word, as Word 2013 call-outs are printing with thick black borders.
Having tried lots of variations, here's my code which worked:
Sub GetWordReference()
'finally got Access to open old version of Word
'open Word 2010
Shell "C:\Program Files (x86)\Office 2010\Office14\winword.exe"
'open Word 2013
'Shell "C:\Program Files\Microsoft Office 15\root\office15\winword.exe"
TryAgain:
On Error GoTo NoWord
Set word2010 = GetObject(, "Word.Application")
On Error GoTo 0
word2010.Visible = True
'word2010.Documents.Add
'word2010.Selection.TypeText "This is Word " & word2010.Version
Exit Sub
NoWord:
Resume TryAgain
End Sub
I can't get the SO code editor to show this correctly, but copying and pasting should work.
I had a similar issue, and thought I would detail my experience for those that stumble across this in the future.
In my situation, I had a Powerpoint macro that was supposed to open a file dialog for the user to select some Excel files and then create tables from the data; I had no problem with it until I recently installed Excel 2003. Now Powerpoint was opening up an Excel 2003 file dialog, which would raise errors when trying to select a *.xlsx file. It didn't matter if I used Excel.Application.10 or Excel.Application.14 in my code to create the Excel object, it was always an Excel 2003 file dialog.
I noticed in Explorer that *.xlsx files were set to be opened in Excel 2010 and *.xls files were set to be opened in Excel 2003. I tried to usual way to reset *.xls files to be opened in 2010 to no avail. I ended up having to delete the registry key and repair Office 2010. Now that all Excel files open in 2010, my problem has been fixed.
I know my problem was a bit different than yours, but I think my experience could help lead to a solution. I think any solution will end up relying on some registry editing.
This is a VB.NET solution:
Sub Word_InfoLate()
Dim wordApp2007 As Object
Dim wordApp2010 As Object
This is a bit intimidating to some, but there may be a registry edit that can solve this.
I am unable to test as I only have one version of MS Office available to me, however, previous versions still have registry keys left over.
I found the 2007 version of Word in the registry, and it's default location is C:\program Files\Microsoft Office\Office14\WINWORD.EXE" indicating that older versions of Word are registered to the newest version install location as it's new default.
What you might be able to do is navigate to the registry location
HKEY_CLASSES_ROOT\Word.Documet.12\shell\Open\Command
Change the (Default) key to read "C:\program Files\Microsoft Office\Office12\WINWORD.EXE" /n "%1"
In theory whenever
Set wordApp2007 = CreateObject("Word.Application.12")
is invoked it may probe the registry for the location of the executable, and find the correct path.