close Password dialog, get next file
Hello,
My problem all stems from trying to skip a Word or Excel document when it is password protected. I'm using a late-bound VB6 exe to access the Office docs.
When Excel 2002 hits the Open statement of an Excel 2007 password protected workbook, it ignores the "Password:=" argument I pass it, and displays the Password dialog instead (this does not happen in older versions of XL).
To correct this, I wrote a separate, stand alone, small VB6 app which just continually sends the ESCAPE character. This sucessfully removes the Password dialog, I capture the error message, skip the file, and go on to the next file.
In Word 2002, I have a test document that does some sort of downloading to a remote server when it is Opened. This of course ties up Word and I've just discovered that the series of ESCAPE characters sent by the separate app causes the "application is busy, Switch To/Retry" dialog to appear.
All I want is a smoothe app, without any dialogs or pop-ups. (it seems impossible) This brings me to the heart of the problem:
Is there any way to capture the Password dialog box and close it without sending ESCAPE characters?
Or how do I unlink Word docs so it doesn't download anything? (at least excel lets you do it in the Open statement "UpdateLinks:=0" ), but Word??
BTW, if it matters, Excel & Word are hidden instances.
Also, they do not want the users to have to interact with the dialog boxes. My app should handle it.
Thanks in advance
added in Edit: I've been reading around - Can multi-threading and use of OleRequestPendingTimeout be used as a solution?
Re: close Password dialog, get next file
Hey CyberJar. Still no answer to your previous thread, huh? With this much varying and undocumented behavior, I don't think your answer lies in using Excel. Perhaps you could use another tool to check the binary file before opening it to see if it is password protected and skip it? Check out this search to get you started. You'll have to find something that works an pick out the relevant parts.
Re: close Password dialog, get next file
Does anyone have this info to share? I've had numerous headaches on how to capture the password dialog handle from the Open statement (Office 2007 doesn't respond as the other versions), but this may shed some light:
Quote:
For an example of how to use the Word Password dialog boxes, see the OpenPwd2 procedure, available in the modCh17 module in WordPasswords.dot in the ODETools\V9\Samples\OPG\Samples\CH17 subfolder on the Office 2000 Developer CD-ROM
Re: close Password dialog, get next file
Hey CyberJar,
Following the links I gave you up there, I took some time to find you a solution to this problem. It was a good challenge. The answer lies in what is called Structured Storage. The dll calls you make to do these checks are located in ole32.dll. I haven't found anyone on the net that has made these calls from vba directly, so I made a DLL to do the check. If you do, please post back here for reference.
To use it, you will have to add this declaration near the top of your module:
Code:
''You must provide the full path unless you place the dll somewhere windows can find it.
Declare Function IsPasswordProtected Lib "C:\path to\OfficeSecurityChecker.dll" _
Alias "_IsFilePassworded@4" (ByVal FileName As String) As Boolean
Now all you gotta do to use it is this:
Code:
Sub Test()
Const fn = "C:\Microsoft Word Document.doc"
If Not IsPasswordProtected(fn) Then
''You can safely open it
End If
End Sub
This should work on any office file or any file that uses structured storage as far as I can tell. NOTE: This only checks if there is a password to open the file, not one to modify it.
You can download the DLL here.
Or, you can compile it yourself using this code:
Code:
#include <stdio.h>
#include <windows.h>
#include <ole2.h>
#include <locale.h>
//Code taken from (and hacked up, of course)
//http://support.microsoft.com/default.aspx?scid=kb;EN-US;186898
extern "C" __declspec(dllexport) bool IsFilePassworded(char *filename);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
// Dump's custom and built-in properties of a compound document.
bool IsFilePassworded(char *filename) {
// Translate filename to Unicode.
WCHAR wcFilename[1024];
setlocale( LC_ALL, "" );
int i = mbstowcs(wcFilename, filename, strlen(filename));
setlocale( LC_ALL, "C" );
wcFilename[i] = 0;
int ret = 0;
IStorage *pStorage = NULL;
IPropertySetStorage *pPropSetStg = NULL;
HRESULT hr;
// Open the document as an OLE compound document.
hr = ::StgOpenStorage(wcFilename, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
if(FAILED(hr)) {
//if(hr == STG_E_FILENOTFOUND)
// printf("File not found.");
//else if(hr == STG_E_FILEALREADYEXISTS)
// printf("Not a compound file.");
//else
// printf("StgOpenStorage() failed w/error %08lx", hr);
return false;
}
// Obtain the IPropertySetStorage interface.
hr = pStorage->QueryInterface(
IID_IPropertySetStorage, (void **)&pPropSetStg);
if(FAILED(hr)) {
//printf("QI for IPropertySetStorage failed w/error %08lx", hr);
pStorage->Release();
return false;
}
// Lookup up security property
IPropertyStorage *pPropStg = NULL;
// Open summary information, getting an IpropertyStorage.
hr = pPropSetStg->Open(FMTID_SummaryInformation,
STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
if(FAILED(hr)) {
//printf("No Summary-Information.\n");
pPropStg->Release();
pPropSetStg->Release();
pStorage->Release();
return false;
}
// Initialize PROPSPEC for the properties you want.
PROPSPEC *pPropSpec = new PROPSPEC[1];
PROPVARIANT *pPropVar = new PROPVARIANT[1];
ZeroMemory(&pPropSpec[0], sizeof(PROPSPEC));
pPropSpec[0].ulKind = PRSPEC_PROPID;
pPropSpec[0].propid = PIDSI_DOC_SECURITY;
// Read properties.
hr = pPropStg->ReadMultiple(1, pPropSpec, pPropVar);
if(FAILED(hr)) {
//printf("IPropertyStg::ReadMultiple() failed w/error %08lx\n",
// hr);
pPropStg->Release();
pPropSetStg->Release();
pStorage->Release();
return false;
}
else {
// Dump properties.
ret = (int)pPropVar->lVal;
}
// De-allocate memory.
delete [] pPropVar;
delete [] pPropSpec;
// Release obtained interfaces.
pPropStg->Release();
pPropSetStg->Release();
pStorage->Release();
if (ret == 1)
return true;
else
return false;
}