How to remove file if application is not running? - windows

Not sure whether this is possible, but I'm creating a file encoding applcation. When a file is decoded, it is saved temporarily in a temp directory, after which it can be opened regularly. However, I actually need to be certain the file is removed as soon as the application that has opened it, has closed it (e.g. has shut down). Otherwise, the decoded (secret) file is just hanging in the temp directory without supervision.
What's more, even when my application itself has been shut down for any reason, I'd like to pass this task on to Windows, if possible. So say the user decodes a file and opens it and then my application is shut down (either normally or abnormally), the decoded file in the temp directory should still be removed as soon as it's not used anymore.
How would I go about this? I've seen tips like FileSystemWatcher and a trivial 'check every second' idea, but if my application is not alive at the moment the decoded file is closed, I'd still like to have the file removed. So I guess I'd need to pass this responbility to Windows, but I'm not sure if that's possible and if so, how.
So how do I remove a file as soon as it's closed if my application isn't running at that particular moment?

Doing this may work:
In the process that creates the file, create it with FileOptions.DeleteOnClose, and with FileShare.ReadWrite (or FileShare.Read if only read access is required from other processes). You may also need FileShare.Delete.
DO NOT let the file close in the main application that created it until the application exits.
In other processes that consume the temporary file, open it with the same file options as the original.
This way, when the last process that has the file open closes, the file will be deleted.
UPDATE:
As noted in the comments, there doesn't seem to be a way in the .NET API to specify both the FIleShare options and the FileOptions.DeleteOnClose. It is possible using straight Win32. I have copied a sample that I tested below. There are 2 programs, one that creates the file, another that consumes it. The only notable difference between the 2 is that the consumer opens the file with OPEN_EXISTING.
Creator
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE fh = CreateFile(
L"yourFilePath\\tempFile.dat",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL,
CREATE_NEW,
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if(fh==INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create file. Error code = " << GetLastError() << std::endl;
return 1;
}
std::cout<< "Hit enter to close.";
std::string inp;
std::getline(std::cin,inp);
CloseHandle(fh);
return 0;
}
Consumer
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE fh = CreateFile(
L"yourFilePath\\tempFile.dat",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if(fh==INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to create file. Error code = " << GetLastError() << std::endl;
return 1;
}
DWORD written;
if(!WriteFile(fh,"Test",4,&written,NULL))
{
std::cerr << "Failed to write data to file. Error code = " << GetLastError() << std::endl;
return 1;
}
std::cout<< "Hit enter to close.";
std::string inp;
std::getline(std::cin,inp);
CloseHandle(fh);
return 0;
}

Use FileOptions.DeleteOnClose.

Things like FileOptions.DeleteOnClose won't help if your media becomes unavailable or the machine gets shut down before the delete occurs. To me this looks very much like an exogenous condition.
Can you stream the decoding to a memory stream rather than to disk and take the whole problem away.

Related

keyboard interrupt routine visual studio C++ console app

I am using VS 2022 Preview to write a C++ console application. I wish to detect a keyboard hit and have my interrupt handler function called. I want the key press detected quickly in case main is in a long loop and therefore not using kbhit().
I found signal() but the debugger stops when the Control-C is detected. Maybe it is a peculiarity of the IDE. Is there a function or system call that I should use?
Edit: I am vaguely aware of threads. Could I spawn a thread that just watches kbd and then have it raise(?) an interrupt when a key is pressed?
I was able to do it by adding a thread. On the target I will have real interrupts to trigger my ISR but this is close enough for algorithm development. It seemed that terminating the thread was more trouble than it was worth so I rationalized that I am simulating an embedded system that does not need fancy shutdowns.
I decided to just accept one character at a time in the phony ISR then I can buffer them and wait and process the whole string when I see a CR, a simple minded command line processor.
// Scheduler.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <Windows.h>
#include <iostream>
#include <thread>
#include <conio.h>
void phonyISR(int tbd)
{
char c;
while (1)
{
std::cout << "\nphonyISR() waiting for kbd input:";
c = _getch();
std::cout << "\nGot >" << c << "<";
}
}
int main(int argc, char* argv[])
{
int tbd;
std::thread t = std::thread(phonyISR, tbd);
// Main thread doing its stuff
int i = 0;
while (1)
{
Sleep(2000);
std::cout << "\nMain: " << i++;
}
return 0;
}

Weird case of AccessViolation while using overlapped IO in Windows

I've been experimenting with Overlapped IO feature of Win32 API, namely ReadFileEx and WriteFileEx functions.
Here is a simplest example:
#include <iostream>
#include <string>
#include <Windows.h>
const DWORD blockSize = 512;
char buffer[blockSize];
bool done = false;
OVERLAPPED overlapped;
void Completion(DWORD error, DWORD read, LPOVERLAPPED overlapped) {
}
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring fileName;
std::wcout << "Enter file name: ";
std::getline(std::wcin, fileName);
HANDLE file = CreateFile(
fileName.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (file == INVALID_HANDLE_VALUE) {
std::wcout << "Error while opening file: " << GetLastError() << std::endl;
std::cin.get();
return -1;
}
overlapped.Offset = overlapped.OffsetHigh = 0;
ReadFileEx(file, buffer, blockSize, &overlapped, (LPOVERLAPPED_COMPLETION_ROUTINE) &Completion);
while (!done)
SleepEx(1000, TRUE);
return 0;
}
As you can see, I'm starting overlapped reading with ReadFileEx and waiting for it to finish using SleepEx. Although Completion has empty body and the program should hang forever after reading first block, it does something completely different. In fact, it raises AccessViolation with code 0xC0000005 on the first call to SleepEx. This happens on Windows machines with Win 7 and Win Vista I've tried, including fresh 64 bit virtual machine with Windows 7. But, curiously, it does not fail on one Windows 8.1 machine and runs just as expected. This was compiled with Visual Studio 2010, but I don't think it matters.
I can not understand what have I done wrong, so if anyone knows the answer, please help me.
The callback must be of the following form, as stated clearly in the documentation:
VOID CALLBACK FileIOCompletionRoutine(
_In_    DWORD        dwErrorCode,
_In_    DWORD        dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
);
Your function has the wrong calling convention. Your cast does not change that. It is simply a way for you to stop the compiler rejecting your ill-formed program. Don't lie to the compiler. Correct the function declaration by adding the CALLBACK calling convention.

Empty Working Set from cmd

I want to write a cmd script to periodically empty the working set from the command prompt. For now I empty the working set in the Rammap tool from sysinternals, but that can't be run by a script.
It's probably easiest to compile something like this:
#include <iostream>
#include <windows.h>
int main(int argc, char **argv) {
if (argc != 2) {
std::cerr << "Usage: min_mem <process_id>\n";
return 1;
}
HANDLE process = OpenProcess(PROCESS_SET_QUOTA, false, atoi(argv[1]));
SetProcessWorkingSetSize(process, -1, -1);
}
...and then run it in your script, something like:
mem_min 1234
...but replacing 1234 with the process ID (in decimal) of the process whose memory you want to minimize.
That said: I'd ask that this answer not be upvoted, since it's really a pretty crappy answer to a question that's basically just a gimme the codez I've been weak enough to post it, but would prefer not to get any rep for doing so.

How do I handle errors in Lua when executing arbitrary strings?

I'm going for absolute minimalism here. (It's been a while since I've worked with the Lua C API.)
#include <lua.hpp>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
lua_State* state = luaL_newstate();
luaL_openlibs(state);
string input;
while (getline(cin, input))
{
auto error = luaL_dostring(state, input.c_str());
if (error)
{
cerr << "Lua Error: " << lua_tostring(state, -1) << '\n';
lua_pop(state, 1);
}
}
lua_close(state);
return 0;
}
This program works fine as long as I feed it perfect Lua. However, if I enter something bad (such as asdf()), the program crashes! Why is it not handling my error gracefully?
I've tried breaking out the calls before. It crashes on the call to lua_pcall itself. I never make it past that line.
The binary download (5.2.1 I believe) has a bug that was corrected in 5.2.3. I rebuilt the library from source, and now my program works fine.

Best way to have crash dumps generated when processes crash?

In Windows environments (XP and Win 7):
What is the best way to automatically have a crash dump generated when processes crash on the system?
Can an installer (MSI) package do this?
One of the best way to have an automatic dump for any/specific process on Windows is to configure a set of entries in the registry. I tried the below on Windows 7 64 bit.
Open notepad.exe, paste the below entry and save it as "EnableDump.reg". You can give any name you wish.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpFolder"=hex(2):44,00,3a,00,5c,00,64,00,75,00,6d,00,70,00,00,00
"DumpCount"=dword:00000010
"DumpType"=dword:00000002
"CustomDumpFlags"=dword:00000000
Double click the "EnableDump.reg" and select 'Yes'. I have given the dump folder as 'd:\dump'. You can change it to whatever folder you wish.
Try to execute a crashing application, Windows will display the error dialog. Choose 'Close the Program' option. After that you will see the dump in the configured folder. The name of the dump file will be .exe..dmp.
For more details, you can refer the below link.
http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx
Below explanation is based on another answer, but the logic is mine (without attribution need, as said on my profile);
Having your own dump generation framework which automatically creates a process dump when any Unhandled exception is encountered, would avoid clients having to install WinDbg.
At the application start up use SetUnhandledExceptionFilter(...) Win32 API to register a callback (i.e. application level exception-handler).
Now the registered callback function is called whenever there is any exception which is not handled. You may then create the process dump using MiniDumpWriteDump(...) API from DbgHelp.dll.
C++ Sample (unicode-enabled)
header-file
#ifndef CRASH_REPORTER_H
#define CRASH_REPORTER_H
//Exclude rarely used content from the Windows headers.
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
#else
# include <windows.h>
#endif
#include <tchar.h>
#include <DbgHelp.h>
class CrashReporter {
public:
inline CrashReporter() { Register(); }
inline ~CrashReporter() { Unregister(); }
inline static void Register() {
if(m_lastExceptionFilter != NULL) {
fprintf(stdout, "CrashReporter: is already registered\n");
fflush(stdout);
}
SetErrorMode(SEM_FAILCRITICALERRORS);
//ensures UnHandledExceptionFilter is called before App dies.
m_lastExceptionFilter = SetUnhandledExceptionFilter(UnHandledExceptionFilter);
}
inline static void Unregister() {
SetUnhandledExceptionFilter(m_lastExceptionFilter);
}
private:
static LPTOP_LEVEL_EXCEPTION_FILTER m_lastExceptionFilter;
static LONG WINAPI UnHandledExceptionFilter(_EXCEPTION_POINTERS *);
};
#endif // CRASH_REPORTER_H
source-file
#include "crash-report.h"
#include <stdio.h>
LPTOP_LEVEL_EXCEPTION_FILTER CrashReporter::m_lastExceptionFilter = NULL;
typedef BOOL (WINAPI *MiniDumpWriteDumpFunc)(HANDLE hProcess, DWORD ProcessId
, HANDLE hFile
, MINIDUMP_TYPE DumpType
, const MINIDUMP_EXCEPTION_INFORMATION *ExceptionInfo
, const MINIDUMP_USER_STREAM_INFORMATION *UserStreamInfo
, const MINIDUMP_CALLBACK_INFORMATION *Callback
);
LONG WINAPI CrashReporter::UnHandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtr)
{
//we load DbgHelp.dll dynamically, to support Windows 2000
HMODULE hModule = ::LoadLibraryA("DbgHelp.dll");
if (hModule) {
MiniDumpWriteDumpFunc dumpFunc = reinterpret_cast<MiniDumpWriteDumpFunc>(
::GetProcAddress(hModule, "MiniDumpWriteDump")
);
if (dumpFunc) {
//fetch system time for dump-file name
SYSTEMTIME SystemTime;
::GetLocalTime(&SystemTime);
//choose proper path for dump-file
wchar_t dumpFilePath[MAX_PATH] = {0};
_snwprintf_s(dumpFilePath, MAX_PATH, L"crash_%04d-%d-%02d_%d-%02d-%02d.dmp"
, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay
, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond
);
//create and open the dump-file
HANDLE hFile = ::CreateFileW( dumpFilePath, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN
, NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
_MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = exceptionPtr;
exceptionInfo.ClientPointers = NULL;
//at last write crash-dump to file
bool ok = dumpFunc(::GetCurrentProcess(), ::GetCurrentProcessId()
, hFile, MiniDumpNormal
, &exceptionInfo, NULL, NULL
);
//dump-data is written, and we can close the file
CloseHandle(hFile);
if (ok) {
//Return from UnhandledExceptionFilter and execute the associated exception handler.
// This usually results in process termination.
return EXCEPTION_EXECUTE_HANDLER;
}
}
}
}
//Proceed with normal execution of UnhandledExceptionFilter.
// That means obeying the SetErrorMode flags,
// or invoking the Application Error pop-up message box.
return EXCEPTION_CONTINUE_SEARCH;
}
usage
#include "3rdParty/crash-report.h"
int main(int argc, char *argv[])
{
CrashReporter crashReporter;
(void)crashReporter; //prevents unused warnings
// [application main loop should be here]
return 0;
}
Windows XP:
The following steps enable automatic crash dumps:
1) Open a command prompt, running as administrator
2) Run drwtsn32 -i. This will install Doctor Watson as the default debugger when something crashes
3) Click Ok
4) From the command prompt, run drwtsn32
5) Set the Crash Dump path to your favorite directory, or leave the default.
6) Set the Crash Dump Type to mini. Note that under some circumstances, we may ask you for a full crash dump.
7) Make sure the Dump All Thread Contexts and Create Crash Dump File options are selected.
8) Click Ok
9) If a user.dmp file already exists in the Crash Dump path, delete it.
Windows 7: Location is:
C:\Users[Current User when app crashed]\AppData\Local\Microsoft\Windows\WER\ReportArchive

Resources