py2exe and win32com with excel - py2exe

I've made a script that that changes the color in an excel file. Herefor I use:
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
Now I want to make an exe file with py2exe. It gives a Key error <000208D5-0000-0000-C000-000000000046>. I know the problem is with the win32com.client, but I can not solve it.
Has anybody an idea?
Tx

Disclaimer- this is mostly a guess:
Try using win32.Dispatch or win32.DispatchEx. EnsureDispatch actually creates a .py file with a class representing the COM object requested and returns that, so it might interact oddly with the py2exe functionality.
I don't know how COM works below the python wrapper, but I'd guess something along the lines of that py2exe might be locking in the COM object data set in the gencache makepy file instead of allowing it to be dynamically generated if in changes within the runtime environment.

I had just solved this problem.
if you want use win32 of com service, first you should ensure that the com service has already running,to check this by executing:
"dcomcnfg" in command line, if com service of excel has start correctly ,you should see "Microsoft Excel Application" in the dcom service list like this:
the correct result should like this
if "Microsoft Excel Application" not in the list, you can solve this problem by Microsoft Excel or Microsoft Word does not appear in DCOM Configuration snap-in

Related

Migrating an old old old VB + MSAccess program to a different computer

I have an old program that was made for us a looong time ago. It consists of a large MDB (Access) file with all the data (no encryption, I can manually open the file and browse all the data) and an EXE file (probably VB?) that was custom made to easily manage the data in the file.
I'm trying to move this program for another user, to run in his own laptop.
First I tried just copying all the files, but I had MSCOM, GRD, LST, and ocx missing file errors. I tracked them all down and regsvr32'd them, and the program seemed to go a little further.
Then I got an ODBC connector error. Playing with ODBC sources manager and I added an entry with the name of the program that points to the specific MBD file. This helped too.
Now program starts and shows all menus, buttons and everything. However, the default record that should be onscreen is empty and as soon as I hit any control (next record, list, etc...) it crashes with a VB error 91:
Run-time Error '91': Object variable or With block variable not set
So it looks like the program can open the database file itself but it cant really access the data inside.
What else can I try to see what I need to set it all up correctly? Is there anything that "spies" inside and VB program to see how it's trying to access the MDB file?
Any help would be appreciated!
Probable cause of your problem is some missing dll/ocx file referenced in your application. Open your exe file with notepad (or notepad++) and find all occurrences of .dll and .ocx files and check if those
files exist at user's laptop. If not, just copy them from your working machine and regsvr32 them.
I will go with #smith suggestion.
While looking at the error message on microsoft's website, below is the solution that applies to your scenerio
"The object is a valid object, but it wasn't set because the object library in which it is described hasn't been selected in the Add References dialog box."
So ensure all files are correctly copied to new system.

How to save files to AppData when using Microsoft Desktop App Converter to convert a Win32 app to UWP?

I have a game that was originally written in QuickBasic in the 1990's. I converted it into a Win32 app using QB64. I then used Microsoft's Desktop App Converter to package it as a UWP app and submit it to the Microsoft Store (it's been accepted).
The game seems to work fine, except for saving files. It throws a permission denied error whenever you try to save a file. From what I've been able to find thus far it seems that UWP apps can't save in the install directory and that is likely what my app is trying to do.
There are a number of code samples available online for taking a Win32 app written in C#, C, C++, etc. and having it use LocalAppData instead. Unfortunately, I'm not seeing anything that will help me with this application.
Is there a way to make saving files work in this instance? I'm hoping that there is perhaps a way to say, "Hey, when I say save a file, I mean save it to the LocalAppData folder for this particular application." This probably needs to be abstract, ideally a declarative part of the appx package that isn't in the QB64 code. Any ideas?
There are two options to fix it (and one way to hack it):
If the file saving is done from your code, change it to write to an accessible location instead, such as localappdata or temp.
If the file saving is done in code you can't change, then you can use the new Package Support Framework to apply a fixup at runtime that redirects the file operations. This is a new framework coming as part of the 1809 update for Windows 10. At the time of this writing this may not be an option for you just yet. Here is the documentation:
https://learn.microsoft.com/en-us/windows/uwp/porting/package-support-framework?context=/windows/msix/render
A hacky way to solve it that you could try would be to add a launcher EXE to your package and make that the app's entrypoint. The launcher would then copy your actual EXE to a writeable location (localappdata, etc.) and then launch it from there. All your file writes will then succeed.

What is a 6210 and 4354 error mean?

http://s4.postimg.org/bkprrelpp/6210.gif
Can someone explain this to me? I set my MCMS.Primary output as instructed by this page.
http://mdc.custhelp.com/app/answers/detail/a_id/19889/~/using-visual-studio-2013-professional-to-build-a-microsoft-visual-basic
I set the registration type to Extract COM information, the Scan At Build to Dependencies and Properties, and checked the COM Interop. But I'm getting an error and a warning after trying to build the project. I tried the help page that pops out after clicking the error message. But I can't find the components view it was referring to. What I want to know is how much important this COM Interop is. And also why sometimes when I build the project the error does not appear. But mostly it does.
One suggestion of that help page told me to register the item mentioned in the error message. An .exe file.
COM extraction is useful for turning self-registration routines into Windows Installer table data. COM Interop is the equivalent for registering managed assemblies for use via COM Interop. In both cases, the resulting registry keys are used to allow other DLLs to instantiate your COM server.
So the fundamental question you have to answer here is whether MCMS.exe is a COM server and registers any such data. If it is and does, then something is wrong with the extraction, and this is a problem. However if MCMS.exe is not a COM server, or does not actually register any relevant COM data, you may need to disable COM extraction.

Excel - Windows 7 Taskbar Progress

Running Excel 2010, I can assuredly always be running these sheets on this version, as it will only be accessed locally exclusively on my work's terminal computers.
I run a number of import process and large folder filtering/printing batch functions via excel. I am wanting to utilize the Windows 7 taskbar progress bar visual while my functions process, giving an idea of how far they are along. Considered going with other visual effects for showing the progress, but this(if possible) seems the most obvious and professional style to do so.
I've been looking thoroughly into trying to make this work, to no avail. My understanding thus far is that I need to impliment the ITaskbarList3 interface, commonly found within the Windows API. From the code I have found showing how to make it work, once implimented the rest seems fairly easy and self-explanatory.
I am completely restricted to using Excel as the basis for the code, no installation permission on the work computers. I can install at home to get any files necessary, and then transfer them. Happy to use any extensive or really backwards ways to get to the end, as the ends justify whatever means it takes.
It would be much easier to use the Excel Status Bar:
Application.StatusBar = "Show progress to user...";
For the Windows & Taskbar progress bar you need to download the
Windows 7 taskbar: Developer Resources.
You'll need to open the sample solution, right click on the Windows7.DesktopIntegration project > properties > Build > Tick Register for COM.
By checking the "Register for COM interop" option in the IDE during development, the IDE will call regasm on the target assembly together with the /codebase option.
This will cause regasm.exe to add the following registry entry for a COM-visible class exported from your assembly :
HKEY_CLASSES_ROOT\CLSID{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\InprocServer32\CodeBase=
This will enable the CLR to locate your assembly by following the path to your assembly.
Without the codebase path, the CLR will have to locate your assembly (and its dependencies) using the standard search algorithm.
Next Build the solution > goto the bin folder the Windows7.DesktopIntegration project and copy the Windows7.DesktopIntegration.DLL and Windows7.DesktopIntegration.TLB to the System32 folder or better yet Register to the GAC.
One related technique that helps the CLR to locate required assemblies is to copy all assemblies (and their dependencies) to the same folder as the client application itself. However, the client application in your case will be Excel. This means that you must copy the assemblies into the same folder as the Excel application (not a good idea).
Once you are able to instantiate the Windows7.DesktopIntegration DLL, you should be able to call the Windows7Taskbar.SetProgressValue method, eg VBA code:
Set Windows7Taskbar = CreateObject("Windows7.DesktopIntegration")
Windows7Taskbar.SetProgressState(form.Handle, Windows7Taskbar.ThumbnailProgressState.Normal)
Windows7Taskbar.SetProgressValue(form.Handle, progress, maximum)

Embedding an application manifest into a VB6 exe

I have recently gone through a bunch of standalone utility apps written in VB6 to make sure that registry virtualization is turned off for Windows Vista and above. I created a standalone manifest file for each exe, set the requestedExecutionLevel appropriately (some of them need to modify HKEY_LOCAL_MACHINE registry keys, others do not), and tested them. They all appear to work correctly.
I have only one small problem remaining. Since they are standalone utilities, people are used to just copying them around the network and running them manually. If anyone forgets to copy the manifest file as well as the exe, then the exe will silently write to the virtualized registry key instead of the real one and cause hard-to-debug problems.
The obvious solution is to embed the manifest into the exe as a resource. All the articles I have read on the net tell you to embed the resource like this:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
This should work just fine, except that the VB compiler always creates the application icon with resource ID = 1. When I tried the above code, Windows refused to run the exe, complaining about a resource error (I'll update this post with the details later). I tried changing the resource ID to another number, after which Windows ran the program successfully but did not recognise the manifest contents.
Does anyone know of a way to get an embedded manifest to work in a VB6 exe, or should I just stick with an external file?
UPDATE 1
The text given above is the whole content of the .rc file. I compile it to a .res file like this:
"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"
And embed it in the VB6 project file like this:
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\WINDOWS\system32\stdole2.tlb#OLE Automation
Form=Main.frm
ResFile32="Resources.res"
IconForm="FMain"
Startup="FMain"
HelpFile=""
Title="Windows Vista Registry Test - VB6"
ExeName32="RegistryTestVB6.exe"
Path32=""
Command32=""
Name="RegistryTestVB6"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionComments="Windows Vista Registry Test - VB6"
VersionCompanyName=""
VersionFileDescription="Windows Vista Registry Test - VB6"
VersionLegalCopyright=""
VersionProductName="Windows Vista Registry Test - VB6"
CondComp=""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
When I read the compiled exe into the VS2008 resource editor, it looks like this:
RegistryTestVB6.exe
Icon
1 [Neutral]
RT_MANIFEST
1 [English (United States)]
Version
1 [English (United States)]
When I construct an exact equivalent VB.NET test app in VS2008, then load that into the resource editor, it looks like this instead:
RegistryTestNET.exe
Icon
32512 [Neutral]
RT_MANIFEST
1 [Neutral]
Version
1 [Neutral]
UPDATE 2
Testing - the .NET exe runs fine on both Windows XP and Windows 7. However, the VB6 exe produces the following error on XP:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
and the following error on 7:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
Looking in the event log I see the following entry:
Activation context generation failed for "RegistryTestVB6.exe". Error in manifest or policy file "RegistryTestVB6.exe" on line 10. Invalid Xml syntax.
Needless to say the XML isn't invalid, it's exactly the same file with the same encoding that I used for the .NET exe, and that one works.
RESOLUTION
The VB6 compiler does indeed require that an arbitrary text file included in a resource must be an exact multiple of 4 bytes. I simply added spaces to the XML until Notepad++ told me that the total file size including BOM was a multiple of 4.
Thanks to both Michael and Jim for pointing me in the correct direction. Just a pity I can't mark you both as the answer!
Interestingly enough, I had to do the exact same thing recently. Following the steps Christian described, I got it to work the first time through. For prosperity, here is the entire workflow I followed:
Created a RC file as described in the orginal question
Created a app.manifest, preserving whitespace characters, which are VERY IMPORTANT for this to work. As stated in previous answers, the file size must be a multiple of 4.
Ran RC.EXE as described in the original question against the rc to generate the .res file
Edited my Project.VBP file to include the following line near the top:
ResFile32="Resources.res"
Built EXE in standard vb6 environment. When deployed on a vista or win7 machine, the shield shows up and the user is prompted to run as administrator. When opening the EXE file in studio, I verified the resources.
Notepad++ tells me that the encoding on my app.manifest file is ANSI. It did not include an byte order mark at the start of the file.
If you are still having troubles, let me know and I'll share whatever I can with you. Other than that, I'm not sure what to tell you other than Works on my Machine!
VB6 has a quirk in that any resource element must be an exact multiple of 4 in length. Try padding the manifest file out with spaces to ensure this, and see if that changes the behavior.
This quirk was documented in Microsoft article Q297112 (archive).
Also, you might add the resource using the VB6 IDE instead of editing the VBP. The effect may be the same, but the resource editor is the standard means for doing this.
Using the Resource Compiler (rc.exe) is going the long way around. There is a much simpler option for embedding an application manifest within an executable, whether C++ or VB6 or just about any other language. The Manifest Tool (mt.exe) was written specifically to embed manifests within binaries and is provided free of charge with the Windows SDK. The added benefit of using mt.exe is that it automatically handles any necessary padding.
Simply run the following command line after the binary has been compiled. I have used the naming convention used internally by the Visual C++ 2005 compiler, where the manifest filename contains the full program name with ".intermediate.manifest" appended.
mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1
Update: I have personally been using this in an automated build process with VB6 executables for over two years now. It has been so successful that we have eliminated OS compatibility tests - specific to manifests - from our regression testing.

Resources