I want to use time related method and function in Win32 VC++ application. VC++ provides CTime class. I want to know that using CTime class in non mfc project is safe. Is there any alternatives for CTime class for using in non mfc win32 application.
Thank you.
You can try using GetSystemTime;
Retrieves the current system date and time. The system time is
expressed in Coordinated Universal Time (UTC).
To retrieve the current system date and time in local time, use the
GetLocalTime function.
A sample code piece.
#include <windows.h>
#include <iostream>
void main(){
SYSTEMTIME st;
GetSystemTime(&st);
char currentTime[84] = "";
sprintf_s(currentTime,"%d/%d/%d %d:%d:%d %d",
st.wDay,st.wMonth,st.wYear, st.wHour,
st.wMinute, st.wSecond , st.wMilliseconds);
std::cout<<"time: "<<currentTime;
getchar();
}
Using MFC in a console (non GUI) application is safe. Even the Project Wizard to generate a Win32 Console Application has a checkbox to specify whether to include the MFC libraries or not.
Related
In my understanding currently there are two ways to copy virtual files from a Shell Namespace Extension with the Explorer so that Copy GUI will be shown to the user:
Via IDataObject interface:
Reading a file is done via IDataObject::GetData that should support CFSTR_FILEDESCRIPTORW, CFSTR_FILECONTENTS and CFSTR_SHELLIDLIST clipboard formats at very minimum. Requesting CFSTR_FILECONTENTS from IDataObject::GetData should create an IStream that is used to access the data. UI is enabled via setting FD_PROGRESSUI flag when CFSTR_FILEDESCRIPTORW is requested.
Via ITransferSource interface:
Reading a file is done via ITransferSource::OpenItem requesting for IShellItemResources. Then IShellItemResources should report {4F74D1CF-680C-4EA3-8020-4BDA6792DA3C} resource as supported (GUID indicating that there is an IStream for the item). Finally an IStream is requested via parent ShellFolder::BindToObject for accessing the data. UI is handled by the Explorer itself, it is always shown.
My problem is: these two mechanisms are working just fine separately (as you can see from the screenshots). But once I enable both IDataObject from IShellFolder::GetUIObjectOf and ITransferSource from IShellFolder::CreateViewObject - the approach via IDataObject is always used leading to the old copy GUI (as on the first screenshot). I see from the trace logs that ITransferSource is requested several times, but no actions are performed, it just gets Released and destroyed right away.
So how may I force Explorer to show fancy copy GUI when copying from my Shell Namespace Extension?
A minimal reproducible example may be found here: https://github.com/BilyakA/SO_73938149
While working on Minimal Reproducible example I somehow managed to make it work as expected with both IDataObject and ITranfserSource interfaces enabled. It happened after:
unregistred x64 build SNE example (regsvr32 /u)
registred x32 build SNE example (it was not working in x64 explorer, root was not opening)
unregistred x32
registred x64 again.
Somehow new copy UI was shown to me when copying the files.
But I was not able to reproduce this result constantly after I have unregistred x64 SNE, restarted explorer and registered SNE x64 again.
What I have tried:
Registred both x32 and x64 SNE - still old GUI
Removed Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Cached value with my NSE GUID and restarted Explorer afterwards. Still old GUI.
I suspect there is some kind of cache (other than Registry) that keeps track if NSE supports ITransferSource. And since I have developed and tested without ITransferSource at the beginning - it is cached that my NSE does not support it even that I have added it later. And somehow registering 32bit reset that cache value.
The current code is doing something like this when asked for an IDataObject:
HRESULT CFolderViewImplFolder::GetUIObjectOf(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT rgfReserved, void **ppv)
{
....
if (riid == IID_IDataObject)
{
CDataObject* dataObject = new (std::nothrow) CDataObject(this, cidl, apidl);
return ::SHCreateDataObject(m_pidl, cidl, apidl, dataObject, riid, ppv);
}
...
}
SHCreateDataObject already creates already a full-blown IDataObject with everything needed from the (optional) input PIDL(s), including all Shell formats for items in the Shell namespace (CFSTR_SHELLIDLIST, etc.).
Passing an inner object 1) will probably conflict with what the Shell does and 2) requires a good implementation (I've not checked it).
So you can just replace it like this:
HRESULT CFolderViewImplFolder::GetUIObjectOf(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT rgfReserved, void **ppv)
{
....
if (riid == IID_IDataObject)
{
return ::SHCreateDataObject(m_pidl, cidl, apidl, NULL, riid, ppv);
}
...
}
In fact, the IDataObject provided by the Shell is complete (supports SetData method, etc.) so you should never need to implement it yourself, it's more complex than it seems. You can reuse it as a general purpose IDataObject (you can pass nulls and 0 for the 4 first arguments).
PS: the Shell also provides the "reverse" method: SHCreateShellItemArrayFromDataObject that gets a list of Shell items from an IDataObject (if the data object contains the expected clipboard formats).
For those who need to use inner IDataObject within SHCreateDataObject for additional format:
Inner IDataObject should support CFSTR_SHELLIDLIST clipboard format in GetData() as well as report this format in EnumFormatEtc(). Supporting SetData() with CFSTR_SHELLIDLIST format is really useful here since DefDataObject sets inner data object with already fully constructed CIDA and you may just store a copy of it.
Once inner data object will report CFSTR_SHELLIDLIST in EnumFormatEtc() and return valid CIDA in GetData() - modern Copy UI will be used since it relies only on PIDL of the items.
I have been having issues using an anonymous mutex (boost::interprocess::interprocess_mutex) in a boost::interprocess::managed_shared_memory instance. Namely, issues arise if the software crashes; the mutex may remain locked (depending on its state at time of crash). It can make debugging interesting too :).
My understanding is that I can substitute the interprocess_mutex with boost::interprocess::file_lock (FL). #DaveF posted some questions that I would like to build upon. I'd like to have a good understanding what I'm getting myself into before I put FL into use.
Can I use an anonymous boost::interprocess::condition_variable (CV) with FL? Having looked through the code, it appears that it will work.
In using a CV, am I opening myself up to the same problems I have experienced when using mutex (ie. if the application unexpectedly ends without proper cleanup/finalisation)?
What is the best way to create a FL. I've thought about something similar to the following...
Note code may not compile:
namespace bi = boost::interprocess;
namespace bf = boost::filesystem;
const std::string strSharedMemName = std::string("cp_shdmem_") + std::to_string(nIdx);
const std::string strNamedMutexName = strSharedMemName + "_mtx";
// I'm working on Linux, but would like to Boost to create a temporary file path.
const bf::path pathTmpFile =
bf::temp_directory_path() / (strNamedMutexName + ".txt");
{
// 1. So can I just create the file? What happens if it exists? Boost docs say this
// about the file_lock constructor:
// "Throws interprocess_exception if the file does not exist
// or there are no operating system resources."
// 2. What happens if file already exists?
bf::ofstream f(pathTmpFile);
}
// Create.
bi::file_lock lockFile(pathTmpFile.string().c_str());
// Lock.
bi::scoped_lock<bi::file_lock> lockNamed(lockFile);
Platform specifics:
Ubuntu 17.10
Boost 1.63
GCC 7.2
Recently, some of our clients lost their XAudio2_7.dll from their C:/Windows/System32 directory, and now they can't hear any audio. Reinstalling DirectX or registering the dll normally would be sufficient enough to fix this problem, but we're looking for a solution that does not require admin rights. This is for Windows 7. Applications are written in CPP, and some of them are 32 bit and the rest are 64 bit.
There is a local copy of XAudio2_7.dll within the same directory of the exe, but that is not loaded unless that dll is registered since it's a COM dll. Registering for the current user (using "Regsvr32.exe /n /i:user XAudio2_7.dll") does not work since the dll does not implement a required interface "DllInstall".
One approach I've tried is to statically link a .lib of XAudio instead of using a dynamic link. Microsoft does not distribute XAudio2_7.lib with DirectX SDK. "No versions of the DirectX SDK contain the xaudio2.lib import library. DirectX SDK versions use COM to create a new XAudio2 object." msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2create%28v=vs.85%29.aspx
Granted, this suggests that it may not be possible to use a static XAudio library even if I created one since it sounds like it depends on external objects defined in other libraries. It was still worth testing in case my hypothesis is incorrect.
Following the steps mentioned in this link: adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/
I didn't get very far with this method. Outside of the articles being dated, there were a couple problems with this. The MS link within the blog mentions this is for 32-bit dlls. Even for 32-bit dlls, dumpbin didn't work since it only exported the interface functions.
Dump of file C:\XAudioTest\32Bit\XAudio2_7.dll
File Type: DLL
Section contains the following exports for xaudio2.dll
00000000 characteristics
4C064181 time date stamp Wed Jun 02 07:33:21 2010
0.00 version
1 ordinal base
4 number of functions
4 number of names
ordinal hint RVA name
1 0 00030AA0 DllCanUnloadNow
2 1 00031150 DllGetClassObject
3 2 00031470 DllRegisterServer
4 3 000314D0 DllUnregisterServer
Summary
C000 .data
1000 .no_bbt
4000 .reloc
1000 .rsrc
7B000 .text
Later, I found this quote from another MSDN article. "The COM standard requires that COM DLLs export DllCanUnloadNow, DllGetClassObject, DllRegisterServer and DllUnregisterServer. Typically they will export nothing else. This means that you cannot get COM object or method information using dumpbin.exe." msdn.microsoft.com/en-us/library/aa446532.aspx
I've also tried using a third party program that claims it's able to create a .lib from a COM dll. www.binary-soft.com/dll2lib/dll2lib.htm
Although this did generate a 32-bit .lib file, compiling with the lib file generated unresolved external symbols. This utility does come with methods to handle unresolved symbols, but entering anything within Symbol Finder or Advanced Conversion Options would crash. Looking in the latest release notes (3.00), I found that they added support for Vista and no mentions for Windows 7. Also this doesn't work for 64-bit dlls.
I've tried another approach is to change the initialization sequence to use a nonregistered COM DLL described in this link: Use COM Object from DLL without register
The initialization code looks similar to this:
HMODULE audioLib = LoadLibrary(TEXT("XAudio2_7.dll"));
if (audioLib == NULL)
{
debugf(TEXT("Failed to create COM object. Unable to load XAudio2_7.dll library. GetLastError: %d"), GetLastError());
return;
}
typedef HRESULT (WINAPI* Function_DllGCO) (REFCLSID, REFIID, LPVOID*);
Function_DllGCO processAddress = (Function_DllGCO)GetProcAddress(audioLib, "DllGetClassObject");
if (processAddress == NULL)
{
debugf(TEXT("COM DLL failed to find the process address to interface function 'DllgetClassObject' within the XAudio2_7.dll. GetLastError: %d"), GetLastError());
return;
}
class __declspec(uuid("{5a508685-a254-4fba-9b82-9a24b00306af}")) xAudioGUID;
REFCLSID classID = __uuidof(xAudioGUID);
class __declspec(uuid("{00000001-0000-0000-c000-000000000046}")) classFactoryGUID;
REFIID classFactoryID = __uuidof(classFactoryGUID);
IClassFactory* ClassFactory = NULL;
if (processAddress(classID, classFactoryID, reinterpret_cast<LPVOID*>(&ClassFactory)) != S_OK)
{
debugf(TEXT("Failed to execute function pointer to DLLGetClassObject. GetLastError: %d"), GetLastError());
return;
}
class __declspec(uuid("{00000000-0000-0000-C000-000000000046}")) unknownGUID;
REFIID unknownID = __uuidof(unknownGUID);
if (ClassFactory->CreateInstance(NULL, unknownID, reinterpret_cast<void**>(&ClassFactory)) != S_OK)
{
debugf(TEXT("Class factory for XAudio2_7 failed to create an object instance. GetLastError: %d"), GetLastError());
ClassFactory->Release();
return;
}
if( XAudio2Create( &XAudio2, 0, AUDIO_THREAD) != S_OK ) //Fails here with error number: 1008 (An attempt was made to reference a token that does not exist.)
{
debugf( NAME_Init, TEXT( "Failed to create XAudio2 interface: GetLastError: %d" ), GetLastError());
return;
}
//Do other things
All WinAPI function calls passed excluding the XAudio2Create function. I'm uncertain why XAudio2Create is not using the object created from the factory, and I don't know what I need to do to get it to use that object. I'm still investigating what I can do here, but it's difficult to debug closed source libraries.
Before I knew about COM DLLs, a method I've tried is to use DLL-Redirection to force an application to use a particular DLL. Using the process described here: DLL redirection using manifests
XAudio2Create still failed. I don't have a strong strategy in identifying what's wrong with the manifest. I also haven't found much up to date documentation regarding manifests for dll redirection. From the sounds of this is this mostly used to load a particular DLL version. I don't think DLL redirection is the method I need since there is already a local copy of XAudio2_7 within the same directory of the exe, which means it should take precedence over the XAudio2_7 within the system directory according to: msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
Note: I removed the hyper links for some addresses since I don't have enough reputation points to post more than 2 links.
Have you tried registration-free activation?
I am exporting a global variable from a dll using __declspec(dllexport) and importing the same in the client exe using __declspec(dllimport).
The global variable in the dll is being updated with time in a separate thread. I want to receive this updated data in my client .exe, but I am not getting it. What I get is the only initial value of the global variable every time I read the data using a timer in the client exe.
What is the explanation of such a behavior? and what can I do to achieve what I want to achieve? Is there an option without including get() and set() exported functions from the dll?
Here is the code that is exported from dll:
typedef struct{
int iTotalQueues;
int iCurrentQueue;
wchar_t szQueueName[100];
}UPDATE_STATUS_DATA;
__declspec(dllexport) UPDATE_STATUS_DATA UpdateStatusData;
This structure members are updated in a loop for a long time. The updating code is in the dll itself.
Here is the code that is imported in the exe:
typedef struct{
int iTotalQueues;
int iCurrentQueue;
wchar_t szQueueName[100];
}UPDATE_STATUS_DATA;
__declspec(dllimport) UPDATE_STATUS_DATA UpdateStatusData;
I am reading this data inside a timer response and not getting the updated values.
The code in your question as you would expect when built into a simple test project. So, here are the two explanations that I can concoct:
You are taking a copy of UpdateStatusData in your executable. And so the changes to the value of UpdateStatusData made in the DLL do not get reflected in the copy.
Your DLL is, for some reason, not modifying the struct.
I'm trying to implement http://msdn.microsoft.com/en-us/library/dd377634%28v=VS.85%29.aspx on Qt, to generate a poster frame/thumbnail for video files.
I have installed both Windows Vista and Windows 7 SDK. I put:
#include "qedit.h"
in my code (noting there is also one in C:\Qt\2010.04\mingw\include), I add:
win32:INCLUDEPATH += $$quote(C:/WindowsSDK/v6.0/Include)
to my *.pro file. I compile and get " error: sal.h: No such file or directory". Finding this in VC++ I add
win32:INCLUDEPATH += $$quote(C:/Program Files/Microsoft Visual Studio 10.0/VC/include)
And now have 1400 compile errors. So, I abandon that and just add:
win32:LIBS += C:/WindowsSDK/v7.1/Lib/strmiids.lib
to my *.pro file and try to run (without including any headers):
IMediaDet mediadet;
But then I get "error: IMediaDet: No such file or directory".
#include "qedit.h"
gives me the same error (it looks like it's pointing to the Qt version) and
#include "C:/WindowsSDK/v6.0/Include/qedit.h"
goes back to generating 1000's of compile errors.
Sigh, so much trouble for what should be 10 lines of code...
Thanks for your comments and help
Since you say you are "a C++/Qt newbie" then I suspect that the real issue may be that you are attempting to load the library yourself rather than simply linking your application to it?
To link an external library into your application with Qt all you need to do is modify the appropriate .pro file. For example if the library is called libfoo.dll you just add
LIBS += -L/path/to/lib -lfoo
You can find more information about this in the relevant section of the qmake manual. Note that qmake commonly employs Unix-like notation and transparently does the right thing on Windows.
Having done this you can include the library's headers and use whatever classes and functions it provides. Note that you can also modify the project file to append an include path to help pick up the headers eg.
INCLUDEPATH += /path/to/headers
Again, more information in the relevant section of the qmake manual.
Note that both these project variables work with relative paths and will happily work with .. to mean "go up a directory" on all platforms.
Note that qedit.h requires dxtrans.h, which is part of DirectX9 SDK.
You can find dxtrans.h in DirectX SDK from August 2006. Note that dxtrans.h is removed from newer DirectX SDKs.
Do you have access to the source of the external library? The following assumes that you do.
What I do when I need to extract a class from a library with only functions resolved, is to use a factory function in the library.
// Library.h
class SomeClass {
public:
SomeClass(std::string name);
// ... class declaration goes here
};
In the cpp file, I use a proxy function outside the extern "C" when my constructor requires C++ parameters (e.g. types such as std::string), which I pass as a pointer to prevent the compiler from messing up the signature between C and C++. You can avoid the extra step if your constructor doesn't require parameters, and call new SomeClass() directly from the exported function.
// Library.cpp
#include "Library.h"
SomeClass::SomeClass(std::string name)
{
// implementation details
}
// Proxy function to handle C++ types
SomeClass *ImplCreateClass(std::string* name) { return new SomeClass(*name); }
extern "C"
{
// Notice the pass-by-pointer for C++ types
SomeClass *CreateClass(std::string* name) { return ImplCreateClass(name); }
}
Then, in the application that uses the library :
// Application.cpp
#include "Library.h"
typedef SomeClass* (*FactoryFunction)(std::string*);
// ...
QLibrary library(QString("MyLibrary"));
FactoryFunction factory = reinterpret_cast(library.resolve("CreateClass"));
std::string name("foobar");
SomeClass *myInstance = factory(&name);
You now hold an instance of the class declared in the library.