I'm writing a DLL in VC++ and I need to use external text file. I have something like this right now:
ifstream file;
string line;
file.open("C:\\Users\\Me\\Desktop\\textfile.txt");
getline(file,line);
file.close();
I understand that I can have this file in Resources right?
I added my text file by going to "ResourceView" -> "Add Resource" -> "Import". I chose my text file and created custom resource type.
How can I access to this file to use similarly to the code above ? I have Resource.h but what should I do with it?
Can I edit my resource text file too?
Assumptions:
The resource type is "TEXT"
The resource ID is MY_RESOURCE_ID (this would be a constant from your resource.h)
You have stored the hInstance for your EXE or DLL (whichever contains the resource) into m_hInstance.
Loading a resource into memory and getting a pointer to it is done like this:
HRSRC hResource = FindResource(m_hInstance, MAKEINTRESOURCE(MY_RESOURCE_ID), L"TEXT");
if (hResource)
{
HGLOBAL hLoadedResource = LoadResource(m_hInstance, hResource);
if (hLoadedResource)
{
LPVOID pLockedResource = LockResource(hLoadedResource);
if (pLockedResource)
{
DWORD dwResourceSize = SizeofResource(m_hInstance, hResource);
if (0 != dwResourceSize)
{
// Use pLockedResource and dwResourceSize however you want
}
}
}
}
Note: You do not have to unload or unlock the resource on 32-bit or 64-bit vesions of Windows, and if you obtain the resource again you will not leak memory; you always get the same piece of memory.
For updating a resource, see Updating Resources in MSDN.
Related
I am trying to load a custom resource (.rc) from a .dll but the FindResource() function always ends up returning NULL
This is my code trying to load the resource:
HINSTANCE FragDll;
FragDll = GetModuleHandleA((LPCSTR)"FragmentShaders.dll");
HRSRC FragResource = FindResource(FragDll, MAKEINTRESOURCE(StartMenu_frag), L"FRAGMENTSHADER");
if (FragResource)
{
HGLOBAL FragLoadedResource = LoadResource(FragDll, FragResource);
if (FragLoadedResource)
{
LPVOID FragLockedResource = LockResource(FragLoadedResource);
if (FragLockedResource)
{
DWORD FragdwResourceSize = SizeofResource(FragDll, FragResource);
if (0 != FragdwResourceSize)
{
// Use pLockedResource and dwResourceSize however you want
}
}
}
}
FragResource for some reason always returns NULL. Does anyone know how to fix this?
Edit:
I have done a breakpoint in visual studios to get more information:
Values during runtime
EDIT:
If this method of loading resources from a .dll doesnt work, please then give another method of reading a resource (.rc) from a .dll.
as others pointed out in the commentaries, the problem here is not that FragRessource is Null, it is null because FragDLL is null in the first place.
So we come to why is FragDLL null ?
As stated in the documentation (https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea) of GetModuleHandleA : "The module must have been loaded by the calling process." Which means you have to load the module before retrieving his handle. You can do so using LoadLibraryExA (https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa).
Hopes this helps
I'm working with the revit api, and one of its problems is that it locks the .dll once the command's run. You have to exit revit before the command can be rebuilt, very time consuming.
After some research, I came across this post on GitHub, that streams the command .dll into memory, thus hiding it from Revit. Letting you rebuild the VS project as much as you like.
The AutoReload Class impliments the revit IExteneralCommand Class which is the link into the Revit Program.
But the AutoReload class hides the actual source DLL from revit. So revit can't lock the DLL and lets one rebuilt the source file.
Only problem is I cant figure out how to implement it, and have revit execute the command. I guess my C# general knowledge is still too limited.
I created an entry in the RevitAddin.addin manifest that points to the AutoReload Method command, but nothing happens.
I've tried to follow all the comments in the posted code, but nothing seems to work; and no luck finding a contact for the developer.
Found at: https://gist.github.com/6084730.git
using System;
namespace Mine
{
// helper class
public class PluginData
{
public DateTime _creation_time;
public Autodesk.Revit.UI.IExternalCommand _instance;
public PluginData(Autodesk.Revit.UI.IExternalCommand instance)
{
_instance = instance;
}
}
//
// Base class for auto-reloading external commands that reside in other dll's
// (that Revit never knows about, and therefore cannot lock)
//
public class AutoReload : Autodesk.Revit.UI.IExternalCommand
{
// keep a static dictionary of loaded modules (so the data persists between calls to Execute)
static System.Collections.Generic.Dictionary<string, PluginData> _dictionary;
String _path; // to the dll
String _class_full_name;
public AutoReload(String path, String class_full_name)
{
if (_dictionary == null)
{
_dictionary = new System.Collections.Generic.Dictionary<string, PluginData>();
}
if (!_dictionary.ContainsKey(class_full_name))
{
PluginData data = new PluginData(null);
_dictionary.Add(class_full_name, data);
}
_path = path;
_class_full_name = class_full_name;
}
public Autodesk.Revit.UI.Result Execute(
Autodesk.Revit.UI.ExternalCommandData commandData,
ref string message,
Autodesk.Revit.DB.ElementSet elements)
{
PluginData data = _dictionary[_class_full_name];
DateTime creation_time = new System.IO.FileInfo(_path).LastWriteTime;
if (creation_time.CompareTo(data._creation_time) > 0)
{
// dll file has been modified, or this is the first time we execute this command.
data._creation_time = creation_time;
byte[] assembly_bytes = System.IO.File.ReadAllBytes(_path);
System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assembly_bytes);
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass && type.FullName == _class_full_name)
{
data._instance = Activator.CreateInstance(type) as Autodesk.Revit.UI.IExternalCommand;
break;
}
}
}
// now actually call the command
return data._instance.Execute(commandData, ref message, elements);
}
}
//
// Derive a class from AutoReload for every auto-reloadable command. Hardcode the path
// to the dll and the full name of the IExternalCommand class in the constructor of the base class.
//
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class AutoReloadExample : AutoReload
{
public AutoReloadExample()
: base("C:\\revit2014plugins\\ExampleCommand.dll", "Mine.ExampleCommand")
{
}
}
}
There is an easier approach: Add-in Manager
Go to Revit Developer Center and download the Revit SDK, unzip/install it, the check at \Revit 2016 SDK\Add-In Manager folder. With this tool you can load/reload DLLs without having to modify your code.
There is also some additional information at this blog post.
this is how you can use the above code:
Create a new VS class project; name it anything (eg. AutoLoad)
Copy&Paste the above code in-between the namespace region
reference revitapi.dll & revitapiui.dll
Scroll down to AutoReloadExample class and replace the path to point
your dll
Replace "Mine.ExampleCommand" with your plugins namespace.mainclass
Build the solution
Create an .addin manifest to point this new loader (eg.
AutoLoad.dll)
your .addin should include "FullClassName" AutoLoad.AutoReloadExample
This method uses reflection to create an instance of your plugin and prevent Revit to lock your dll file! You can add more of your commands just by adding new classes like AutoReloadExample and point them with seperate .addin files.
Cheers
I'm been trying to start doing a plug-in for a program called "Euroscope" for quite some time and i still can't do anything. I even read a C++ book and nothing, it's too difficult to start.
The question i'm going to ask is a little bit specific and it's going to be difficult to explain but i'm tired of trying to solve this by my own so here it comes.
I have a class that i imported with a bunch of function prototypes in the header called "EuroscopePlugIn".
My principal .cpp is this:
void CPythonPlugInScreen::meu()
{
//loop over the planes
EuroScopePlugIn::CAircraft ac;
EuroScopePlugIn::CAircraftFlightPlan acfp;
CString str;
CPythonPlugIn object;
for(ac=GetPlugIn()->AircraftSelectFirst();
ac.IsValid();
ac=GetPlugIn()->AircraftSelectNext(ac))
{
EuroScopePlugIn::CAircraftPositionData acpos=ac.GetPosition();
const char *c=ac.GetCallsign();
object.printtofile_simple_char(*c);
object.printtofile_simple_int(ac.GetState());
};
object.printtofile_simple_int(ac.GetVerticalSpeed());
object.printtofile_simple_int(acfp.GetFinalAltitude());
cout<<acfp.GetAlternate();
}
the "printtofile_simple_int" and "printtofile_simple_char" are defined is the class CPythonPlugIn like this:
void printtofile_simple_int(int n){
ofstream textfile;
textfile.open("FP_simple_int.txt");
textfile<<(n);
textfile.close();
So i open the program, load the .dll i created with Build->Solution and it does nothing, the .txt files aren't even created and even the cout produces nothing.
I will give you some of the prototype infos on the header file "EuroScopePlugIn.h" in case you need them to understand my micro program. If you need other,ask me and i'll put it here
//---GetPlugIn-----------------------------------------------------
inline CPlugIn * GetPlugIn ( void )
{
return m_pPlugIn ;
} ;
&
CAircraft AircraftSelectFirst ( void ) const ;
//-----------------------------------------------------------------
// Return :
// An aircraft object instance.
//
// Remark:
// This instance is only valid inside the block you are querying.
// Do not save it to a static place or into a member variables.
// Subsequent use of an invalid extracted route reference may
// cause ES to crash.
//
// Description :
// It selects the first AC in the list.
//-----------------------------------------------------------------
&
int GetFinalAltitude ( void ) const ;
//-----------------------------------------------------------------
// Return :
// The final requested altitude.
//-----------------------------------------------------------------
Please guys i need help to start with the plug-in making, from that point on with a methodology of trial and error i'll be on my way. I'm just finding it extremely hard to start...
Thank you very much for the help
My file is located in C:\\Input\\pStep.p21 . i want to open that file in my cpp program. How can i do it? I am using char* inputPath="C:\\Input\\pStep.p21"; but its not finding my file in program. How to get current working directory in VC++?. Its working if try to save p21 file but failing if i read it.
my code in CAA:
#include<CATSDM_Services>
#include<SdaiModel.h>
#include<CATIUniCodeString>
---
---
main()
{
CATIUniCodeString inputPath("C:\\Input\\pStep.p21");
HRESULT hr=S_OK;
SdaiModel edxModel=Null;
//this method reads express schema name, input p21 file and sdaimodel
hr=CreateModelFromFile(inputPath,"parts",edxModel);
if(FAILED(hr))
{
cout<<"Model created succesfully";
}
else
{
cout<<"Failed";
}
}
Sorry for not seeing the question earlier.
From what I am seeing in your code, the test is wrong. The FAILED() macro denotes incorrect execution. Thus from you code, if you see "Failed" on the console, it actually means the execution of the method ran OK.
Change your code to something like:
if ( SUCCEEDED(hr) )
{
cout<<"Model created succesfully";
}
else
{
cout<<"Failed";
}
I want to create a .stl file for a particular shape where each face of that shape has a different patch name like face1,face 2 etc. I have done this by overriding the StlAPI_Writer and RWStl classes in opencascade. I have used file.Append method instead of file.Build method to do so.
But I have a problem when I save the .stl file in an already existing file, it appends data to the existing one which is incorrect. I want to delete the existing data in the file and append new data face by face for a given shape.
Please help me on this.
You can use this simple function:
#include <sys/stat.h>
#include <string>
using namespace std;
bool FileExists(string strFilename) {
struct stat stFileInfo;
bool blnReturn;
int intStat;
// Attempt to get the file attributes
intStat = stat(strFilename.c_str(),&stFileInfo);
if(intStat == 0) {
// We were able to get the file attributes
// so the file obviously exists.
blnReturn = true;
} else {
// We were not able to get the file attributes.
// This may mean that we don't have permission to
// access the folder which contains this file. If you
// need to do that level of checking, lookup the
// return values of stat which will give you
// more details on why stat failed.
blnReturn = false;
}
return(blnReturn);
}
I assume you use the SaveFileDialogue class. In this case you can handle the return result of the dialogue like this:
if ( saveFileDialog.ShowDialog() == ::DialogResult::OK ) {
if ( FileExist(saveFileDialog.FileName) ) {
// erase the file
}
// write the code using the Append function
}
This should work, however a easier variant must be accessible if you use something else than Append (something like Write or maybe even Append but with a parameter that specifies to rewrite the file)
HTH, JP