ESRI AppRef Throws Com 8000FFFF error - c#

i am using the arcGIS api to make a plugin for arcFM, when i try to run this code
Type t = Type.GetTypeFromProgID("esriFramework.AppRef");
System.Object obj = Activator.CreateInstance(t);
pApp = obj as IApplication;
i get
System.Runtime.InteropServices.COMException(0x8000FFFF): Creating an instance of the component with CLSID {Appref CLSID HERE} from the IClassFactory faileddue to the following error: 8000ffff
Thanks

This was impossible i needed to be using arcMap not ArcFM

In the AppRef CoClass documentation, it says:
Note you can only use the AppRef
object if your code is running inside
one of the ArcGIS application
processes.
Forum posts seem to confirm that this is the same error which is seen when this constraint has been violated:
From http://forums.esri.com/Thread.asp?c=93&f=1729&t=217861:
It is my understanding that there is
indeed no way to access the
IApplication instance from a
geoprocessing script.
In theory, if your task is purely
geoprocessing, you should be able to
do it all without accessing the
IApplication object.
It looks like the OP of the above forum post was able to get around their problem by "using IToolboxWorkspace and accessing directely the Esri-toolboxes". This was her code:
public IGPTool GetTool(string _sToolName, string _sToolboxName)
{
IWorkspaceFactory pGPTFact;
IToolboxWorkspace pToolboxWorkspace;
IGPToolbox pGPToolbox;
IGPTool pGPTool;
pGPTFact = new ToolboxWorkspaceFactoryClass();
pToolboxWorkspace = pGPTFact.OpenFromFile(
ArcGISInstallFolder + #"\ArcToolbox\Toolboxes", 0) as IToolboxWorkspace;
pGPToolbox = pToolboxWorkspace.OpenToolbox(_sToolboxName);
pGPTool = pGPToolbox.OpenTool(_sToolName);
return pGPTool;
}
private string ArcGISInstallFolder
{
get
{
if (string.IsNullOrEmpty(this.m_sArcGISInstallFolder))
{
Microsoft.Win32.RegistryKey regkey;
regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
#"Software\ESRI\ArcGIS", false);
this.m_sArcGISInstallFolder = regkey.GetValue("InstallDir") as String;
}
return this.m_sArcGISInstallFolder;
}
}
Perhaps you can accomplish your goal either without the AppRef object or by running your script from inside the application.

Related

Context.GetExternalFilesDir() is not accepting null

I am trying to get the path to the private external storage directory of my c# xamarin android app. The microsoft docs tell us to use
Android.Content.Context.GetExternalFilesDir(string)
However, when I try to use this function, I get the following error regarding that function:
An object reference is required for the non-static field, method or property
This is my code
class RecorderController {
string externalStoragePath;
public RecorderController() {
externalStoragePath = Path.Combine(Context.GetExternalFilesDir(null), "recordings");
// I have also tried the following:
// string s = null;
// externalStoragePath = Path.Combine(Context.GetExternalFilesDir(s), "recordings");
// Even when I try to get the path to the Downloads folder, I get the same error:
// string s = Android.OS.Environment.DirectoryDownloads;
// externalStoragePath = Path.Combine(Context.GetExternalFilesDir(s), "recordings");
}
}
I have no clue how to solve this, does anybody know what I am doing wrong?
Try to change
externalStoragePath = Path.Combine(Context.GetExternalFilesDir(null), "recordings");
to
externalStoragePath = Path.Combine(GetExternalFilesDir(null).AbsolutePath, "recordings");
Apparently I had to use an instance of Context, like Mike Christensen commented. I also missed that GetExternalFilesDir returns a File object, and that I should use AbsolutePath after it, like Leo Zhu said.
I changed my code to
class RecorderController {
string externalStoragePath;
public RecorderController(Context con) {
PermanenteOpslagPad = Path.Combine(con.GetExternalFilesDir(null).AbsolutePath, "recordings");
}
}

set up Firebasefirestore Xamarin.android error

recently i've been trying to set up a connection to my Firestore database. I followed the instructions given in this video only that there is a runtime exception when it tries to get the data base via GetDatabase()
public static FirebaseFirestore GetDatabase()
{
FirebaseFirestore database;
var app = Firebase.FirebaseApp.InitializeApp(Application.Context);
if (app == null)
{
var options = new Firebase.FirebaseOptions.Builder()
.SetProjectId("fulcrum-7c537")
.SetApplicationId("fulcrum-7c537")
.SetApiKey("AIzaSyA8lo7k0EFPNR32-g4xdBnMkQnycn_v4G8")
.SetDatabaseUrl("https://fulcrum-7c537.firebaseio.com")
.SetStorageBucket("fulcrum-7c537.appspot.com")
.Build();
app = Firebase.FirebaseApp.InitializeApp(Application.Context , options);
}
database = FirebaseFirestore.GetInstance(app);
return database;
}
The Exception :
Java.Lang.NoClassDefFoundError
Message=Failed resolution of: Lcom/google/common/io/BaseEncoding;
I have been trying for a while to find out why it happens but found nothing. May someone has a solution?
Thanks!
I had exactly the same issue. I downloaded the code provided by Ufinix (the creator of the video). I downgraded the Xamarin.Google.Guava current version 28.2.0 I used, to the 27.1.0.1 version he used in his example. And finally, it worked.

C# : Get COM object from the Running Object Table

I'm working a project that uses API from a third party COM Server. The COM Server is a local server (out of process exe) on which I have no control.
I'm trying to access COM objects from the runnin object table to choose between the several instances of COM objects started with each instance of the application :
private static List<object> GetRunningInstances(string progId) {
// get Running Object Table ...
IRunningObjectTable Rot = null;
GetRunningObjectTable(0, out Rot);
if (Rot == null)
return null;
// get enumerator for ROT entries
IEnumMoniker monikerEnumerator = null;
Rot.EnumRunning(out monikerEnumerator);
if (monikerEnumerator == null) return null;
monikerEnumerator.Reset();
List<object> instances = new List<object>();
IntPtr pNumFetched = new IntPtr();
IMoniker[] monikers = new IMoniker[1];
while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0) {
IBindCtx bindCtx;
CreateBindCtx(0, out bindCtx);
if (bindCtx == null) continue;
Guid clsid = Type.GetTypeFromProgID(progId).GUID;
string displayName;
Guid monikerClsid;
Guid riid = Marshal.GenerateGuidForType(typeof(IApplication));
object obj;
monikers[0].GetDisplayName(bindCtx, null, out displayName);
monikers[0].GetClassID(out monikerClsid);
if (displayName.IndexOf(clsid.ToString(), StringComparison.OrdinalIgnoreCase) > 0) {
//monikers[0].BindToObject(bindCtx, null, ref unkid, out obj);
Rot.GetObject(monikers[0], out obj);
instances.Add((IApplication)obj);
}
}
}
If I start two instances of the target application, the ROT dump shows two instances of the corresponding COM object (named IApplication here) as GetDisplayName shows the right clsid for the interface IApplication registered in the registry.
The problem is that the objects I get from Rot.GetObject are described as System.__ComObject and cannot be cast to IApplication (InvalidCastException because QueryInterface failed with E_NOINTERFACE) even if their moniker describe the right clsid...
I tried casting it progammatically to every available type in my project just to see but the only success is casting it to System.__ComObject...
I also tried using IMoniker.BindToObject instead of Rot.GetObject but this time, I get a FileNotFound Exception when I provide the corresponding interface GUID. BindToObject works when I provide the riid for IUnknown but it gives me a System.__ComObject I can't cast (back to square one !).
For information, in the ROT dump, I can also shows a file moniker corresponding to an open project in the target app but I cannot create a COM object from this either.
Anyone has an idea about how to correctly retrieve the objects from the ROT ?
Thanks,
Regards.
EDIT :
After a few days out and a new eye on this problem, I discovered the CLSID in the moniker's display name is not the exact same one I want but has two digits off (the indexof test turns out to be wrong).
After carefully reading the clsid's it turns out that the clsid in the moniker's displayname is the clsid of the coclass of IApplication and not the clsid of IApplication.
I tried casting the object to "ApplicationClass" (the aforedmentionned coclass) but this gives me an exception. The additional info I get (in french) could translate as follows : Impossible to cast __ComObject wrapper instances to another class but it's possible to cast these instances to interfaces as long as the underlying com component supports QueryInterface calls for the interface IID.
Any idea on how to proceed from here ?
I don't now if you still have a problem but since there is no answer yet I want to share what I've done after couple of weeks research about handling multiple COM Interfaces on ROT.
I've fetched all the objects from ROT and store them in hashtable to ensure uniqueness via Key/Value but you can adjust it to a List as you prefer on question. You just need to fetch running object value to add your List.
public static Hashtable GetRunningObjectTable()
{
Hashtable result = new Hashtable();
IntPtr numFetched = new IntPtr();
IRunningObjectTable runningObjectTable;
IEnumMoniker monikerEnumerator;
IMoniker[] monikers = new IMoniker[1];
GetRunningObjectTable(0, out runningObjectTable);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
{
IBindCtx ctx;
CreateBindCtx(0, out ctx);
string runningObjectName;
monikers[0].GetDisplayName(ctx, null, out runningObjectName);
object runningObjectVal;
runningObjectTable.GetObject(monikers[0], out runningObjectVal);
result[runningObjectName] = runningObjectVal;
}
return result;
}
After that you can cast the object stored in your List to your COM Interface. For instance, I've also shared my way which works for Rhapsody COM Interface in below;
Hashtable runningObjects = GetRunningObjectTable();
IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
while (rotEnumerator.MoveNext())
{
string candidateName = (string)rotEnumerator.Key;
if (!candidateName.StartsWith("Rhapsody"))
continue;
rhapsody.RPApplication app = rotEnumerator.Value as rhapsody.RPApplication;
if (app == null)
continue;
// Do your stuff app (com object) in here..
}

How to get instance from calling application

I have a plugin for a third-party application that calls a C#.NET method and I need to get the instance from the calling application.
_MapInfoApplication = (MapInfo.MapInfoApplication) System.Runtime.InteropServices.Marshal.GetActiveObject("Mapinfo.application");
Gives me an active instance from the application, but in the case there is two open instances of the application I can't know if I got the right one, is there way to determine who called?
Use the System.Runtime.InteropServices.Marshal.GetObjectForIUnknown method, passing an object pointer using the IDispatchID from MapInfo as a parameter:
public static void MINote(int MIWindowID, string Message)
{
System.IntPtr MIDispatchPtr = new IntPtr(MIWindowID);
DMapInfo MIConnection = (DMapInfo)Marshal.GetObjectForIUnknown(MIDispatchPtr);
MIConnection.Do(String.Format("Note \"Note from CSharp: {0}\"",Message));
DMBApplications Applications = (DMBApplications) MIConnection.MBApplications;
foreach (DMapBasicApplication mbApp in Applications)
{
MIConnection.Do(String.Format("Note \"MB App. running in this MapInfo instance: {0}\"", mbApp.Name));
}
}

How the JIT compiler decide when to initialize static constructors

Recently I have observed the following interesting scenario in one of the application I'm developing using .NET 3.5. In this particualr application I have a singletion object which I access as a static variable. I exepected that the .NET run time should initializes this singleton object at the very first time I access it, but it seems this is not the case. .NET runtime initialize it way before I access this particualr object. Following is some peudo code,
if(!initSingleton)
//Do some work without using the singletion class.
else
//Do some work using the singletion class.
Even at runtime my code only executes the code in side the if statement .NET runtime still initializes the singleton object. In some of the application runs I don't need to access this pariticualr object at all!
Also I don't see this behavior with debug builds. Seems this has something to do with optimized builds (release builds).
Is this is the expected behavior of the .NET runtime?
Update:
Following is the actual code,
private void InitServiceClient(NetworkCredential credentials, bool https)
{
string uri = currentCrawlingWebUrl;
if (!uri.EndsWith("/"))
uri = string.Concat(uri, "/");
uri = string.Concat(uri, siteDataEndPointSuffix);
siteDataService = new SiteData.SiteDataSoapClient();
siteDataService.Endpoint.Address = new EndpointAddress(uri);
if (credentials != null)
{
siteDataService.ClientCredentials.Windows.ClientCredential = credentials;
}
else if (MOSSStateHandler.Instance.UserName.Length > 0 && MOSSStateHandler.Instance.Password.Length > 0)
{
siteDataService.ClientCredentials.Windows.ClientCredential.UserName = MOSSStateHandler.Instance.UserName;
siteDataService.ClientCredentials.Windows.ClientCredential.Password = MOSSStateHandler.Instance.Password;
siteDataService.ClientCredentials.Windows.ClientCredential.Domain = MOSSStateHandler.Instance.Domain;
}
BasicHttpBinding httpBinding = (BasicHttpBinding)siteDataService.Endpoint.Binding;
httpBinding.Security.Mode = (https ? BasicHttpSecurityMode.Transport : BasicHttpSecurityMode.TransportCredentialOnly);
string authmode = MOSSConnectorConfiguration.Instance.Config.GetString(ConfigConstants.SHAREPOINT_AUTH_PROVIDER, "ntlm");
if (authmode.Equals("ntlm", StringComparison.OrdinalIgnoreCase))
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
else if (authmode.Equals("kerberos", StringComparison.OrdinalIgnoreCase))
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
else
throw new Exception(string.Format("Not supported"));
}
Even though my application doesn't execute the code in side else if block the class MOSSStateHandler get initialized.
I suggest you read Jon Skeet's article about Singleton pattern in C#, and its appendix about lazy-loading etc. You'll get better understanding about the implementation issues.
From C# language spec:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
An instance of the class is created.
Any of the static members of the class are referenced.

Categories

Resources