generate temporary filename with .ico extension on windows - c

I wish to generate a temporary filename that ends with the extension .ico using the windows C API.
I have tried using GetTempFileName but then I cannot control the extension.

The only reasons why you'd want to use GetTempFileName is, because it guarantees to produce a unique file name. Appending an arbitrary extension breaks that invariant, so that is not a solution.
So you need a solution that produces a unique file name. Using the string representation of a GUID is a common way to get that:
std::wstring GetUniqueFileName( const std::wstring& extension = std::wstring() ) {
GUID guid{ 0 };
_com_util::CheckError( ::CoCreateGuid( &guid ) );
wchar_t buffer[39];
if ( !::StringFromGUID2( guid, buffer, sizeof( buffer ) / sizeof( *buffer ) ) ) {
throw std::runtime_error( "StringFromGUID2() failed." );
}
std::wstring retVal{ buffer };
retVal += extension;
return retVal;
}

Related

Splitting a string without a delimeter in c

I want to trim this string below (which is a log.txt file) into the substring below.
Since there are no delimeters, I can't use strtok().
So how could I do it?
Log file's contents:
[INFO][2019-10-2323:21:45.638]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0001"}
[INFO][2019-10-2323:22:11.936]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0001"}
[INFO][2019-10-2323:22:29.232]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0002"}
[INFO][2019-10-2323:22:29.256]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0002"}
[INFO][2019-10-2323:22:33.192]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0003}
[INFO][2019-10-2323:22:48.075]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0003"}
[INFO][2019-10-2323:22:48.098]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0004"}
[INFO][2019-10-2323:22:52.034]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0004"}
[INFO][2019-10-2323:25:58.509]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0005"}
[INFO][2019-10-2323:26:42.425]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0005"}
[INFO][2019-10-2323:27:15.467]{"cmd":"set","objects":[{"type":"switch","data":["zwave-dc53:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"DC530401010001","reqid": "0006"}
[INFO][2019-10-2323:27:42.030]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-dc53:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"DC53010401000000","reqid": "0006"}
[INFO][2019-10-2323:32:45.088]{"cmd":"set","objects":[{"type":"switch","data":["zwave-ffa2:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"FFA20401010001","reqid": "0033"}
[INFO][2019-10-2323:33:11.934]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-ffa2:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"FFA2010401000000","reqid": "0007"}
[INFO][2019-10-2323:36:39.262]{"cmd":"set","objects":[{"type":"switch","data":["zwave-ffa2:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"FFA20401010001","reqid": "0008"}
[INFO][2019-10-2323:36:39.267]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-ffa2:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"FFA2010401000000","reqid": "0008"}
[INFO][2019-10-2323:36:39.267]{"cmd":"set","objects":[{"type":"switch","data":["zwave-ffa2:4-1"],"execution":{"command":"OnOff","params":{"on":true}}}],"raw":"FFA20401010001","reqid": "0022"}
[INFO][2019-10-2323:36:39.332]{"cmd":"status","objects":[{"bridge_key":"zwave","data":[{"hash":"zwave-ffa2:8-0","states":{"OnOff":{"on":false}}}],"type":"switch"}],"raw":"FFA2010401000000","reqid": "0009"}
The substring I want to find is the raw data's value, for example: FFA2010401000000
This should work to extract the raw data, assuming it's hex-encoded data (error checking, memory freeing, and proper headers are omitted for clarity):
#define RAW_STR ",\"raw\":\""
FILE *logfile = fopen( filename, "rb" );
char *line = NULL;
size_t len = 0;
for ( ;; )
{
ssize_t bytesRead = getline( &line, &len, logfile );
if ( bytesRead == -1 )
{
break;
}
char *rawData = strstr( line, RAW_STR );
if ( !raw )
{
continue;
}
// jump over the "raw":" string to the actual value
rawData += strlen( RAW_STR );
// assume the data is hex
unsigned long long value = strtoull( rawData, NULL, 16 );
...
}
This simple method depends on the log file being consistently formatted. If the log file doesn't always have the RAW_STR in that exact format, it won't work.
I've also assumed you're running on a POSIX system and have access to getline().
You might find regular expression useful in this scenario. Specifically regexec seems appropriate here.
int regexec(const regex_t *preg, const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags);
Or a proper json parser. Checkout the c library section on the json format description website.

SNMP Agent: Could mib2c generate code for InetAddress or String type (ie something not an integer type)

I was able to transform 95% of a dedicated MIB to C code and make it run in a sub-agent like described in the last part of this Net-SNMP tutorial
For this I naturally use the mib2c.mfd.conf (I just read that mfd stands for Mib For Dummies ... all is said ...)
mib2c -I -c mib2c.mfd.conf my_mib_node
It generated a long .c file with almost all the oids like the one below.
Almost no lines were generated for the VideoInetAddr OID
//ABSTRACT OF SOURCE FILE GENERATED BY MIB2C
//...
long VideoFormat = 0; /* XXX: set default value */
// <<<=== NOTHING GENERATED HERE FOR VideoInetAddr OF TYPE INETADDRESS
// WHEREAS OTHER INTEGERS ARE NORMALLY PRESENT
long VideoInetPort = 0; /* XXX: set default value */
//...
void init_my_mib_node(void)
{
//...
const oid VideoFormat_oid[] = { 1,3,6,1,4,1,a,b,c,d,e };
static netsnmp_watcher_info VideoFormat_winfo;
// <<<=== NO OID GENERATED for VideoInetAddr OF TYPE INETADDRESS
// WHEREAS OTHER OIDs ARE NORMALLY GENERATED
static netsnmp_watcher_info VideoInetAddr_winfo; //We have the winfo after all
const oid VideoInetPort_oid[] = { 1,3,6,1,4,1,a,b,c,d,g };
static netsnmp_watcher_info VideoInetPort_winfo;
DEBUGMSGTL(("my_mib_node",
"Initializing VideoFormat scalar integer. Default value = %d\n",
VideoFormat));
reg = netsnmp_create_handler_registration(
"VideoFormat", NULL,
VideoFormat_oid, OID_LENGTH(VideoFormat_oid),
HANDLER_CAN_RWRITE);
netsnmp_init_watcher_info(&VideoFormat_winfo, &VideoFormat,
sizeof(long),ASN_INTEGER, WATCHER_FIXED_SIZE);
if (netsnmp_register_watched_scalar( reg, &VideoFormat_winfo ) < 0 ) {
snmp_log( LOG_ERR, "Failed to register watched VideoFormat" );
//...
}
This worked fine and needed 5 minutes (no code to write, just call the init() function), I was able to GET and SET all ... integers ...
Some oids are of Type InetAddress were not generated, neither were strings
Question
Is there a mib conf file able to generate code for every type
I tried the mib2c.old-api.conf which generates code also for the non-integer oids but I find it not as convenient. There is more boilerplate code to write.
Yes, mib2c could generate code for IP addresses. I cannot say that mfd does this, but, definitely, some mib2c.iterate.conf (for tables) does this.
The type of IP in SNMP is ASN_IPADDRESS represented by unint32_t in C.
Also,You need to make sure that in MIB-file for object, which represents IP, you have "SYNTAX IpAddress".
Have a look:
at the MIB file with IP object and implementation in C
Piece of answer but I am very far from comprehension and so side problems persist
Very pragmatically I managed to add by hand
//I put here ONLY what I added, see question above to complete code
#define STR_LENGTH_IPV4 sizeof("xxx.yyy.zzz.www")
char VideoInetAddr[STR_LENGTH_IPV4] = "192.168.2.3";
//...
const oid VideoInetAddr_oid[] = { 1,3,6,1,4,1,a,b,c,d,f };
reg = netsnmp_create_handler_registration(
"VideoInetAddr", NULL,
VideoInetAddr_oid, OID_LENGTH(VideoInetAddr_oid),
HANDLER_CAN_RWRITE);
netsnmp_init_watcher_info(&VideoInetAddr_winfo, &VideoInetAddr, sizeof(VideoInetAddr),
ASN_OCTET_STR, WATCHER_MAX_SIZE );
if (netsnmp_register_watched_scalar( reg, &VideoInetAddr_winfo ) < 0 ) {
snmp_log( LOG_ERR, "Failed to register watched VideoInetAddr" );
}
It still need to understand exactly the option like WATCHER_MAX_SIZE (is-it the good one ?)

Unique String generator

I want to make a program (network server-client).
One of the specification for this program is next:
The server will receive the sent packages and save it into a file, with a unique name (generated by the server at the moment the transfer starts.
Ex __tf_"unique_random_string".txt
I made a function that returns a pointer to a "unique" string created.
The problem is: If i stop the server and then start it again it will generate the same names.
Ex:this file names were generated and then i stopped the server.
__ft_apqfwk.txt
__ft_arzowk.txt
__ft_cdyggx.txt
I start it again and i try to generate 3 file names. Them will be the same.
Sorry for my english. I'm still learning it.
My function to generate this "unique string" is:
char *create_random_name(void)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
char *file_name;
int i=0;
int key;
if((file_name = malloc(16 * sizeof ( char )) ) == NULL)
{
printf("Failed to alloc memory space\n");
return NULL;
}
strcpy(file_name,"__ft_");
for(i=5 ; i<11 ; i++)
{
key = rand() % (int)(sizeof(charset)-1);
file_name[i]=charset[key];
}
strcat(file_name,".txt");
file_name[15] = '\0';
return file_name;
}
One option is saving to a file the names that have been used, and using them as a checklist. You also want to seed rand with something like srand(time(NULL)).
another is ignoring the randomisation, and just going in order, e.g. aaa, aab aac...aba ,abb etc. Again, save where your cycle is up to on a file.
Your question seems a little bit unclear but if you want to generate a unique string there are a couple of things you can consider:
Get System timestamp ( yyyy-MM-dd-HH-mm-ss-fff-tt)
Use Random function to generate a random number
Combine this with your function and I am sure you will get a unique string.
Hope it helps !
If it's available, you could avoid manually generating random names that might collide and let the system do it for you (and handle collision resolution by creating a new name) by using mkstemps. This is also safer because it opens the file for you, removing the risk of a random name being generated, verified to be unique, then trying to open it and discovering another thread/process raced in and created it.
char name[] = "/path/to/put/files/in/__ft_XXXXXX.txt";
int fd = mkstemps(name, strlen(".txt"));
if (fd == -1) { ... handle error ... }
After mkstemps succeeds, name will hold the path to the file (it's mutated in place, replacing the XXXXXX string), and fd will be an open file descriptor to that newly created file; if you need a FILE*, use fdopen to convert to a stdio type.
Before calling rand(),--- once and only once---, call srand(time()) to initialize the random number generator.
Before settling on any specific file name, call stat() to assure that file name does not already exist.

Check if a file is a specific type in C

I'm writing my first C program, though I come from a C++ background.
I need to iterate through a directory of files and check to see if the file is a header file, and then return the count.
My code is as follows, it's pretty rudimentary I think:
static int CountHeaders( const char* dirname ) {
int header_count = 0;
DIR* dir_ptr;
struct dirent* entry;
dir_ptr = opendir( dirname );
while( ( entry = readdir( dir_ptr ) ) )
{
if ( entry->d_type == DT_REG )
{
//second if statement to verify the file is a header file should be???
++header_count;
}
}
closedir( dir_ptr );
return header_count;
}
What would be a good if statement to check to see if the file is a header?
Simply check if the file extension is .h, something like:
const char *ext = strrchr (entry->d_name, '.');
if ((ext != NULL) && (!strcmp (ext+1, "h"))) {
// header file
}
Ofcourse, note that this assumes all your header files have an .h extension, which may or may not be true, the C standard does not mandate that header files must have an .h extension.
Each dirent structure has a d_name containing the name of the file, so I'd be looking to see if that followed some pattern, like ending in .h or .hpp.
That would be code along the lines of:
int len = strlen (entry->d_name);
if ((len >= 2) && strcmp (&(entry->d_name[len - 2]), ".h") == 0))
header_count++;
if ((len >= 4) && strcmp (&(entry->d_name[len - 4]), ".hpp") == 0))
header_count++;
Of course, that won't catch truly evil people from calling their executables ha_ha_fooled_you.hpp but thanfkfully they're in the minority.
You may even want to consider an endsWith() function to make your life easier:
int endsWith (char *str, char *end) {
size_t slen = strlen (str);
size_t elen = strlen (end);
if (slen < elen)
return 0;
return (strcmp (&(str[slen-elen]), end) == 0);
}
:
if (endsWith (entry->d_name, ".h")) header_count++;
if (endsWith (entry->d_name, ".hpp")) header_count++;
There are some much better methods than checking the file extension.
Wikipedia has a good article here and here. The latter idea is called the magic number database which essentially means that if a file contains blah sequence then it is the matching type listed in the database. Sometimes the number has restrictions on locations and sometimes it doesnt. This method IMO is more accurate albeit slower than file extension detection.
But then again, for something as simple as checking to see if its a header, this may be a bit of overkill XD
You could check if the last few characters are one of the header-file extensions, .h, .hpp, etc. Use the dirent struct's d_name for the name of the file.
Or, you could run the 'file' command and parse its result.
You probably just want to check the file extension. Using dirent, you would want to look at d_name.
That's up to you.
The easiest way is to just look at the filename (d_name), and check whether it ends with something like ".h" or ".hpp" or whatever.
Opening the file and actually reading it to see if it's valid c/c++, on the other hand, will be A LOT more complex... you could run it through a compiler, but not every header works on its own, so that test will give you a lot of false negatives.

What is the Windows equivalent of "pidof" from Linux?

In a batchscript, I need to get a list of process IDs with given binary path C:\path\to\binary.exe.
In Linux, I can just do pidof /path/to/binary.
Is there a Win32 executable which does the same, supported from WinXP Home to Win7 (tasklist won't work)?
The package which includes this has to be portable, so a 10MB download is not what I'm looking for.
Is there a C function available which does this and is supported from WinXP to Win7? Note: I want to match a process path, not a filename which could be used by other applications too.
wmic.exe is available on XP, Vista and 7 and can do this. However, it does not come with Windows XP Home edition.
wmic process where ExecutablePath='C:\\windows\\system32\\notepad.exe' get ProcessId
If you want support for Windows XP Home too, you can use EnumProcess and GetModuleFileNameEx. The downside here is that you won't be able to query names of processes running by another user if you're not running as administrator. QueryFullProcessImageName will probably do the trick here, but it's Vista+.
If that's not enough, you'll need Process32First (swatkat's code). For each process you need to call Module32First and then get MODULEENTRY32->szExePath. Note that even this is not completely portable and will not work well on x64 where you'll need QueryFullProcessImageName.
You can use Toolhelp APIs to enumerate processes, get their full path and compare it with the required process name. You need to walk the modules list for each process. The first module in the list is the process executable itself. Here's a sample code:
int main( int argc, char* argv[] )
{
if( argc > 1 )
{
printf( "\nGetting PID of: %s\n", argv[1] );
HANDLE hProcSnapshot = ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( INVALID_HANDLE_VALUE != hProcSnapshot )
{
PROCESSENTRY32 procEntry = {0};
procEntry.dwSize = sizeof(PROCESSENTRY32);
if( ::Process32First( hProcSnapshot, &procEntry ) )
{
do
{
HANDLE hModSnapshot = ::CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procEntry.th32ProcessID );
if( INVALID_HANDLE_VALUE != hModSnapshot )
{
MODULEENTRY32 modEntry = {0};
modEntry.dwSize = sizeof( MODULEENTRY32 );
if( Module32First( hModSnapshot, &modEntry ) )
{
if( 0 == stricmp( argv[1], modEntry.szExePath ) )
{
printf( "\nPID: %ld\n", procEntry.th32ProcessID );
::CloseHandle( hModSnapshot );
break;
}
}
::CloseHandle( hModSnapshot );
}
}
while( ::Process32Next( hProcSnapshot, &procEntry ) );
}
::CloseHandle( hProcSnapshot );
}
}
return 0;
}
You can write a small C# application which first calls Process.GetProcessesByName(String) , then go over the results and print the Id property of each one when the MainModule.FileName is equal to the path you are looking for.
PowerShell can solve your problems, if is buit in in Win 7, and downloadable on the other OSs.
param($fileName)
Get-Process | where -FilterScript {$_.MainModule.FileName -eq $fileName}
This script will receive one parameter, the filename you are looking for, and it will output the filename of its executable.
You can call this from a bat file by doing:
powershell -Command "& {Get-Process | where -FilterScript {$_.MainModule.FileName -eq %FILENAME%}"

Resources