DeleteFile() doesn't work in Embarcadero C++ Builder - c++

I load several pdfs into Embarcadero C++ and digitally sign them with Gnostice pdfToolkit Vcl. The problem is deleting the unsigned pdf when it is already signed.
This is the code:
gtPDFDocumento->LoadFromFile("no_firmado.pdf");
gtPDFDocumento->AddSignature(firma_digital.pfx);
gtPDFDocumento->SaveToFile("firmado.pdf");
//You have to reload the pdf because if it does not give an error
gtPDFDocumento->LoadFromFile("firmado.pdf");
//
if(!DeleteFile("no_firmado.pdf"){
int e = GetLastError();
AnsiString error = SysErrorMessage(e);
ShowMessage(error);
return;
}
This is the result of the error with GetLastError():
The process does not have access to the file because it is being used
by another process.
I would like to know how I can unlock the unsigned pdf in order to delete it.
I had already tried that code and it gives the same error:
gtPDFDocument->LoadFromFile("not_signed.pdf");
gtPDFDocument->AddSignature(digital_signature.pfx);
gtPDFDocument->SaveToFile("signed.pdf");
//You have to reload the pdf because if it does not give an error
gtPDFDocument->LoadFromFile("signed.pdf");
//
// Free Resources
gtPDFDocument->Reset();
// Destroy PDF document object
FreeAndNil(gtPDFDocument);
// After this point gtPDFDocument can not be used unless reinitialized.
if(!DeleteFile("not_signed.pdf"){
inte = GetLastError();
AnsiString error = SysErrorMessage(e);
ShowMessage(error);
return;
}
Thank you!!

You still have the no_firmado.pdf file open from the line where you load it originally.
gtPDFDocumento->LoadFromFile("no_firmado.pdf");
This is why you are getting this error.
Close the file explicitly and after that, it can be deleted.
// Free Resources
gtPDFDocumento->Reset();
// Destroy PDF document object
FreeAndNil(gtPDFDocumento);
// After this point gtPDFDocumento can not be used unless reinitialized.
Now you can call DeleteFile(...)

Related

How Open a user-defined extension file in Program?

I'm programming a data logger GUI software using Borland C++Builder 2006. It's my Company desired platform.
I'm saving received data after some analyzing in specific files with my defined extension as ".evp" . I have defined Save and Open Functions in my programs that worked fine.
Now I have problem with how to open my saved file directly without using my software. I mean when I double-click on a saved file, it open automatically with my software and show data. Then there is two Question :
How I tell windows to open this ".evp" file with my software.
How I handle the opened file in my software and use it my defined Open function.
by Borland C2006 you mean Embarcadero BDS2006 Turbo(explorer) C++?
File associations are stored somewhere in registry
See Create registry entry to associate file extension with application in C++. So you can create reg file or add registry entries programaticaly by WinAPI.
I never updated registry in my apps but this is example of how you can read registry (obtaining CPU frequency):
double getregfcpu()
{
DWORD keyhnd;
HKEY hKey=NULL;
DWORD dwSize;
DWORD dwFrequency;
double f=0.0;
for(;;)
{
keyhnd=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0",0,KEY_QUERY_VALUE,&hKey);
if (keyhnd!=ERROR_SUCCESS) break;
dwSize = sizeof(dwFrequency);
keyhnd = RegQueryValueEx (hKey,"~MHz",NULL,NULL,(LPBYTE)&dwFrequency,&dwSize );
if (keyhnd!=ERROR_SUCCESS) break;
f=dwFrequency; f*=1e6;
break;
}
if (hKey!=NULL) RegCloseKey(hKey);
return f;
}
so experiment/use RegCreateKeyEx instead of RegOpenKeyEx. Strongly recommend to experiment first on some own registry entry not related to windows so you do not mess something up. And only when working as should change the entry name to desired location.
Application side
Go to your App source file (the one that opens when you open project in IDE). Find there WinMain function and change it like this:
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdl, int)
{
try
{
Application->Initialize();
Application->Tag=(int)cmdl; // *** ADD THIS LINE ***
Application->CreateForm(__classid(TMain), &Main);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
The cmdl holds the pointer to the command line with which your application was called. So copy it to your Application->Tag which is intend for any user defined behavior. This way the cmdl is accessible from whole project (in any window/form). Now to extract the file to open you just do in your Form constructor something like this:
AnsiString cmdl=(LPSTR)Application->Tag; // access the command line parameters
if (cmdl.Length()>2) // file is encapsulated with ""
if (cmdl[1]=='"')
if (cmdl[cmdl.Length()]=='"')
{
AnsiString s="";
for (int i=2;i<cmdl.Length();i++) s+=cmdl[i]; // cut of the ""
// here load file: s
}
If you want to have more command line options then you need to upgrade this a bit by searching for the "" first and process all the command line switches ... Sometimes it is useful to use Application exe local path. You can get it like this:
AnsiString exepath=ExtractFilePath(Application->ExeName);

Trying to use URLRequestInfo::SetStreamToFile and URLResponseInfo::GetBodyAsFileRef

I am working on an NaCl plugin for Chrome, and trying to download a URL resource file locally, into the temporary cache of Chrome, but without success.
Here is how I proceed:
// I indicate that I want the resource to be downloaded to a file
m_URLRequestInfo.SetStreamToFile( true );
// I open the request:
m_URLLoader.Open( m_URLRequestInfo, m_CCFactory.NewCallback( &MyClass::OnOpen ) );
...
// My callback (OnOpen) is eventually called.
// I then check to make sure the status code is 200 using this call:
m_URLLoader.GetResponseInfo().GetStatusCode()
// Then I ask to download the whole file:
m_URLLoader.FinishStreamingToFile( m_CCFactory.NewOptionalCallback( &MyClass::OnFileDownloaded ) );
...
// My other callback (OnFileDownloaded) gets eventually called,
// and again the status code is 200.
// Then I query the FileRef using this call:
pp::FileRef l_FileRef = m_URLLoader.GetResponseInfo().GetBodyAsFileRef();
The returned pp::FileRef seems to be fine, but pp::FileRef::GetFileSystemType() returns PP_FILESYSTEMTYPE_EXTERNAL, and then the call to pp::FileRef::GetPath() fails (it returns an UNDEFINED pp::Var).
So from this point, I am lost. I don't know what else I should do to get a valid pp::FileRef that points to a local file in the browser's cache. My final goal is to open this local file (an image file in my case) using a standard system file IO like fopen().
Thanks for any light !
Is there a reason you can't use the nacl_io library instead? With it you can write something like this:
#include <stdio.h>
#include <sys/mount.h>
// Mount an HTTP filesystem that reads files from "http://example.com/path/...".
mount("http://example.com/path/", "/mnt/http", "httpfs", 0, "");
// Performs a URL Request of "http://example.com/path/my_image.png".
FILE* file = fopen("/mnt/http/my_image.png", "r");
...
Take a look a the nacl_io demo in the SDK. It is located at $NACL_SDK_ROOT/examples/demo/nacl_io.
After reading more thoroughly the documentation and running more tests, I finally figured out what I was doing wrong.
When we call pp::URLLoader::FinishStreamingToFile, then the file is downloaded in Browser's cache, but it cannot be opened/read using regular stdio services like fopen, fread etc. We need to use the pp::FileIO class services to open the obtained pp::FileRef and read the content of the file.
So here is what I did to successfully load and read a file that was downloaded for me by the Browser. Basically, I continued to use the C++ PPAPI services.
(1) upon callback from m_URLLoader->FinishStreamingToFile, we then call m_FileIO->Open to open the downloaded file using the obtained FileRef;
(2) upon callback from m_FileIO->Open, we then call m_FileIO->Query to obtain the size of the downloaded file (and some other file attributes);
(3) upon callback from pp::FileIO::Query, we then check the file attribute type (e.g. not a folder), allocate a memory buffer large enough to hold the whole file content, and start to call pp::FileIO::Read to obtain the file's content;
(4) upon callback from pp::FileIO::Read, if the obtained nResult argument is 0, then we reached the EOF and we finished reading the file content into our memory buffer; if the obtained nResult > 0, then it indicates the number of successfully read bytes, and we call m_FileIO->Read again to continue reading bytes, and storing them at a different offset location into our memory buffer; if the obtained nResult < 0 then an error occurred and we must terminate the reading process.
Many steps, and many callbacks to manage, but in the end this works smoothly.

Error loading cr2 with edsdk

I am trying to read cr2 images using canon sdk (canon_edsdk-2.12).
I seem to be loading the dll correctly, but when I try to get the actual image, I get an error.
I tried to run the sample program to see how that is different than mine, but the same thing happens.
Trying to look for the issue on the web, I found the actual source code of the sample: http://read.pudn.com/downloads107/sourcecode/graph/texture_mapping/440409/RAWDevelop/RAWDevelopDlg.cpp__.htm
My error, on the given source, is in the void CRAWDevelopDlg::LoadImage() function -
err = EdsGetImage( m_ImageRef , source , kEdsTargetImageType_RGB , rect , size , DstStreamRef );
if( err == EDS_ERR_OK ) {...}
else
{
AfxMessageBox("The error occurred with the EdsGetImage function.");
}
The above (on line 481 on the page) is the same method that I use, and i get the same error - with error code 35 (instead of 0).
The error seems to be
#define EDS_ERR_FILE_OPEN_ERROR 0x00000023L
So... could there be something wrong with the files ? I experimented with files taken by different versions, including the newest cameras... The files open in Photoshop... And the demo does show header information, as it gives the error. So it can see something.
Am I missing anything ?
All the required dll's used are on the system path...
Thank you.
Old question, still, might help someone:
To open a raw file with the SDK you need to call these functions (you should check for errors, of course):
EdsStreamRef stream = NULL;
EdsImageRef imgRef = NULL;
EdsCreateFileStream("filename", kEdsFile_OpenExisting, kEdsAccess_Read, &stream);
EdsCreateImageRef(stream, &imgRef);
EdsRelease(stream);
Then you can set and get properties with the imgRef.
To save the image as jpg/tiff/RGB image use EdsSaveImage function.

Receiving a Sharing Violation Opening a File Code 32

I have been trying the following piece of code that does not work. What I am trying to do is to start executing my exe (one that I created a simple dialog based application using VC6.0) then from inside this application modify its own contents stored on the hard drive.
So there is a running copy of the exe and from this running copy it will open the disk copy into a buffer. Once loaded into a buffer then begin a search for a string. Once the string is found it will be replaced with another string which may not be the same size as the original.
Right now I am having an issue of not being able to open the file on disk for reading/writing. GetLastError returns the following error "ERROR_SHARING_VIOLATION The process cannot access the file because it is being used by another process.".
So what I did I renamed the file on disk to another name (essential same name except for the extension). Same error again about sharing violation. I am not sure why I am getting this sharing violation error code of 32. Any suggestions would be appreciated. I'll ask my second part of the question in another thread.
FILE * pFile;
pFile = fopen ("Test.exe","rb");
if (pFile != NULL)
{
// do something like search for a string
}
else
{
// fopen failed.
int value = GetLastError(); // returns 32
exit(1);
}
Read the Windows part of the File Locking wikipedia entry: you can't modify files that are currently executing.
You can rename and copy them, but you can't change them. So what you are trying to do is simply not possible. (Renaming the file doesn't unlock it at all, it's still the same file after the rename, so still not modifiable.)
You could copy your executable, modify that copy, then run that though.

Sharing violation on file which really should be closed

I have an application that modifies an XML file by:
(a) opening it,
(b) creating a temporary file and writing a modified version to it,
(c) closing both files, and
(d) replacing the original file with the temporary file.
When I test it on my laptop running Vista, everything works just as it should. On an embedded PC running XP Professional SP2 with a flash drive instead of a hard disk (which may or may not be relevant), it fails at step (d) with an access violation (error code 5).
If I insert code between steps (c) and (d) to verify that the files are closed, it confirms that they are; if I put in code between steps (c) and (d) to try to delete the original file, it fails with a sharing violation (code 32). If I pause the program at this point and try to delete the file from the GUI, it fails with a sharing violation. If I use systinternals "Process Explorer" at this point, it shows the application still has a handle to the file.
Here is some of the code:
// Open the file which is to be updated:
_wfopen_s(&inStream, m_fileName, L"r, ccs=UTF-8");
// Obtain a suitable temporary filename from the operating system:
TCHAR lpTempPathBuffer[MAX_PATH]; // Buffer to hold temporary file path
TCHAR szTempFileName[MAX_PATH]; // Buffer to hold temporary file name
GetTempPath(MAX_PATH, lpTempPathBuffer);
GetTempFileName(lpTempPathBuffer,
TEXT("TMP"),
0,
szTempFileName);
// Now open a temporary file to hold the updates:
errno_t err = _wfopen_s(&outStream, szTempFileName, L"w, ccs=UTF-8");
if (err == 0)
printf ("Temporary file opened successfully\r\n");
else
printf ("Temporary file not opened; error code %d\r\n", err);
Then the gubbins that modifies the file, and then ...
// Finally, we must close both files and copy the temporary file to
// overwrite the original input file:
int closerr = fclose(inStream);
if (closerr == 0)
printf("Original file closed properly\r\n");
else
printf("Original file not closed properly\r\n");
closerr = fclose(outStream);
if (closerr == 0)
printf("Temp file closed properly\r\n");
else
printf("Temp file not closed properly\r\n");
int numclosed = _fcloseall();
printf("Number of files closed = %d\r\n", numclosed);
// Should be zero, as we've already closed everything manually
if (!DeleteFile(m_fileName))
{
int err = GetLastError();
printf ("Delete file failed, error code was %d\r\n", err);
}
else
printf ("Delete file succeeded\r\n");
if (!MoveFileEx(szTempFileName, m_fileName,
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH))
{
int err = GetLastError();
printf ("Move file failed, error code was %d\r\n", err);
}
else
printf ("Move file succeeded\r\n");
The output log shows:
"Temporary file opened successfully
Original file closed properly
Temp file closed properly
Number of files closed = 0
Delete file failed, error code was 32
Move file failed, error code was 5"
This makes no sense... Why am I getting a sharing violation on a file which the operating system insists is closed? And is there a reason why this works in Vista but not in XP?
Many thanks for any advice,
Stephen.
One thing to keep in mind with Flash media is that the access times can be much longer, and the file actions are frequently handled asynchronously. Windows may be returning to your code saying that the file is closed before the device driver has actually released it. You go to delete it, and it's really still in use, according to the device driver.
I'd suggest putting a delay in there for testing purposes (say 5-10 seconds), after the file closes and before you try to delete the file. If it works, then what you need to do is to loop on the delete action a couple of times (with a short delay in the loop) and exit the loop when the delete succeeds, or you hit a max # of attempts (say 4-5).
If you still have the same problem, even with a 30 second delay, then the problem probably lies somewhere else.
It seems to be a problem with file permissions. After trying various other things which didn't work, I decided to try opening the file with read/write permissions (i.e with the "r+" attribute rather than "r"), and then overwriting the original file contents with the contents of the temporary file. This time, the "_wfopen_s" command itself failed with error code 13 ("Permission denied"), indicating that the operating system was clearly not willing to let the program tamper with this file under any circumstances.
So I guess I need to frame the question slightly differently: why, when
(a) my application works perfectly as-is in Vista, and
(b) I can freely edit the file when I am using the GUI in XP, and all the file permissions look to be set correctly, and
(c) the program that is trying to modify the file is running from a session that is 'logged in' as the file owner
...can the file not be modified by the program?
Is this a curiosity of XP, or of the fact that it's running on an embedded computer with flash memory? If it were the latter, I'd expect there to be problems when creating brand new temporary files as well, but this seems to work just fine.
I'd once again value any suggestions.
Stephen