- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个在本地运行的 c# 应用程序,我有一个用 c# 编写的 .dll。
我的应用程序包含
namespace MyApplication
{
public interface IMyInterface
{
IMyInterface Instance { get; }
int MyProp { get; }
}
class MyClass : IMyInterface
{
public int MyProp { get; private set; }
private MyClass instance
public static IMyInterface
{
get
{
if (instance == null)
{
instance = new MyClass();
}
return instance;
}
}
private MyClass() { MyProp = 1; }
}
}
我的图书馆:
namespace MyLibrary
{
public LibClass
{
public static int GetProp()
{
//I want to get the running instance of MyApplication
//If MyApplication is not running I want to start a new instance
//From my application instance I want to
//return the value from MyInterface.Instance.MyProp
}
}
}
一些谷歌搜索让我查看了某种 COM 服务器,但不清楚这是否是最佳方法。我什至不知道要用谷歌搜索什么。最终 MyInterface
会变得复杂很多,并且会包含通知 MyLibrary
刷新数据的事件。实现这一目标的最佳方法是什么?它是 COM 服务器吗?我想在 MyLibrary
使用的 MyApplication
中创建某种 API 吗?
附加信息:
我的 .dll 正在创建为 excel 的实时数据服务器。我希望能够从 excel 访问我的应用程序中的数据并通知 excel 刷新。我不希望我的应用程序有多个实例,因为用户输入将决定 excel 中显示的值。我能够创建 rtd 服务器,但是我不确定访问外部数据的最佳方式是什么。
编辑:
在做了更多研究之后,我想我对在 MyLibrary
中使用 GetActiveObject("MyApplication.IMyInterface")
很感兴趣
namespace MyLibrary
{
public LibClass
{
public static int GetProp()
{
running_obj = System.Runtime.InteropServices.Marshal.GetActiveObject("MyApplication.IMyInterface")
return ((IMyInterface) running_obj).MyProp;
}
private object running_obj = null;
}
}
但我不确定如何在 ROT 中注册 MyApplication.MyClass
。代码原样抛出异常
Invalid class string (Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING))
最佳答案
MyApplication
中添加 public event ComEvent MyApplicationClose;
以在关闭时调用。我能够使用 Managed Event Sinks 使事件正常工作. 编辑反射(reflect)在下面的代码中。
namespace ole32
{
public class Ole32
{
[DllImport( "Ole32.Dll" )]
public static extern int CreateBindCtx( int reserved, out IBindCtx
bindCtx );
[DllImport( "oleaut32.dll" )]
public static extern int RegisterActiveObject( [MarshalAs( UnmanagedType.IUnknown )] object punk,
ref Guid rclsid, uint dwFlags, out int pdwRegister );
[DllImport( "ole32.dll", EntryPoint = "GetRunningObjectTable" )]
public static extern int GetRunningObjectTable( int reserved, out IRunningObjectTable ROT );
[DllImport( "ole32.dll", EntryPoint = "CreateItemMoniker" )]
public static extern int CreateItemMoniker( byte[] lpszDelim, byte[] lpszItem, out IMoniker ppmk );
/// <summary>
/// Get a snapshot of the running object table (ROT).
/// </summary>
/// <returns>A hashtable mapping the name of the object
// in the ROT to the corresponding object</returns>
public static Hashtable GetRunningObjectTable()
{
Hashtable result = new Hashtable();
IntPtr numFetched = IntPtr.Zero;
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;
}
}
}
我的应用程序将充当数据服务器。它接收和处理来自多个来源的数据。对这些数据的访问是通过 COM 公开的。只有一个 MyApplication 实例减少了与外部数据源的连接和处理的冗余,同时允许多个客户端使用它获取的数据。
namespace MyNamespace
{
[ComVisible( true ),
GuidAttribute( "14C09983-FA4B-44e2-9910-6461728F7883" ),
InterfaceType( ComInterfaceType.InterfaceIsDual )]
public interface ICOMApplication
{
[DispId(1)]
int GetVal();
}
//Events for my com interface. Must be IDispatch
[Guid( "E00FA736-8C24-467a-BEA0-F0AC8E528207" ),
InterfaceType( ComInterfaceType.InterfaceIsIDispatch ),
ComVisible( true )]
public interface ICOMEvents
{
[DispId( 1 )]
void ComAppClose( string s );
}
public delegate void ComEvent( string p );
[ComVisible(true)]
[Guid( "ECE6FD4C-52FD-4D72-9668-1F3696D9A99E" )]
[ComSourceInterfaces( typeof( ICOMWnEvents) )]
[ClassInterface( ClassInterfaceType.None )]
public class MyApplication : ICOMApplication, IDisposable
{
//ICOMEvent
public event ComEvent ComAppClose;
protected MyApplication ()
{
//check if application is registered.
//if not registered then register the application
if (GetApiInstance() == null)
{
Register_COMI();
}
}
// UCOMI-Version to register in the ROT
protected void Register_COMI()
{
int errorcode;
IRunningObjectTable rot;
IMoniker moniker;
int register;
errorcode = Ole32.GetRunningObjectTable( 0, out rot );
Marshal.ThrowExceptionForHR( errorcode );
errorcode = BuildMoniker( out moniker );
Marshal.ThrowExceptionForHR( errorcode );
register = rot.Register( 0, this, moniker );
}
public void Dispose()
{
Close( 0 ); //close and clean up
}
//Will look for an existing instance in the ROT and return it
public static ICOMApplication GetApiInstance()
{
Hashtable runningObjects = Ole32.GetRunningObjectTable();
IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
while ( rotEnumerator.MoveNext() )
{
string candidateName = (string) rotEnumerator.Key;
if ( !candidateName.Equals( "!MyNamespace.ICOMApplication" ) )
continue;
ICOMApplication wbapi = (ICOMApplication ) rotEnumerator.Value;
if ( wbapi != null )
return wbapi;
//TODO: Start the application so it can be added to com and retrieved for use
}
return null;
}
//Builds the moniker used to register and look up the application in the ROT
private static int BuildMoniker( out IMoniker moniker )
{
UnicodeEncoding enc = new UnicodeEncoding();
string delimname = "!";
byte[] del = enc.GetBytes( delimname );
string itemname = "MyNamespace.ICOMApplication";
byte[] item = enc.GetBytes( itemname );
return Ole32.CreateItemMoniker( del, item, out moniker );
}
protected void Close( int i )
{
//Deregistering from ROT should be automatic
//Additional cleanup
if (ComAppClose != null) ComAppClose("");
}
~MyApplication()
{
Dispose();
}
//implement ICOMApplication interface
private static int i = 0;
public int GetVal()
{
return i++; //test value to return
}
}
}
注意:这包含一个用于注册程序集的构建后事件
C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe $(TargetFileName) /codebase /tlb:$(TargetName)TypeLib.tlb
由于它是通过 COM 实现的,因此它应该适用于任何 COM 语言,但我只尝试过 c#。最初,此代码将放入 RTDserver for excel。这将允许用户构建复杂的工作表,利用来 self 的应用程序的实时数据。
首先,我在点网中为我的 COM 对象创建了一个包装器。
namespace COMTest
{
//extend both the com app and its events and use the event sink to get the events
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public sealed class MyAppDotNetWrapper, ICOMEvents, ICOMApplication
{
private ICOMApplication comapp;
public MyAppDotNetWrapper()
{
StartEventSink()
}
//Manage the sink events
private void StartEventSink()
{
//get the instance of the app;
comapp = MyApplication .GetApiInstance();
if (comapp != null)
{
serverconnected = true;
//Start the event sink
IConnectionPointContainer connectionPointContainer = (IConnectionPointContainer) comapp;
Guid comappEventsInterfaceId = typeof (ICOMApplicationEvents).GUID;
connectionPointContainer.FindConnectionPoint(ref comappEventsInterfaceId, out connectionPoint);
connectionPoint.Advise(this, out cookie);
}
}
private void StopEventSink()
{
if (serverconnected)
{
//unhook the event sink
connectionPoint.Unadvise(cookie);
connectionPoint = null;
}
}
//Implement ICOMApplication methods
public int GetVal()
{
return comapp.GetVal();
}
//receive sink events and forward
public event ComEvent ComAppCloseEvent;
public void ComAppClose(string s)
{
serverconnected = false;
ComAppCloseEvent(s);
}
private ICOMApplication comapp;
IConnectionPoint connectionPoint;
private int cookie;
private bool serverconnected;
}
}
现在我可以在我的 .net 应用程序中使用我的包装器
namespace COMTest
{
class Program
{
private static MyAppDotNetWrapper app;
static void Main( string[] args )
{
//create a new instance of the wrapper
app = new MyAppDotNetWrapper();
//Add the onclose event handler
app.ComAppCloseEvent += OnAppClose;
//call my com interface method
Console.WriteLine("Val = " + app.GetVal().ToString());
Console.WriteLine("Val = " + app.GetVal().ToString());
string s = Console.ReadLine();
}
static voic OnClose(string s)
{
Console.WriteLine("Com Application Closed.");
}
}
}
输出在哪里
Val = 1
Val = 2
关闭 COM 服务器应用程序后,您会看到关闭消息。
Val = 1
Val = 2
Com Application Closed.
Running Object Table: Provider in .NET, consumer in MFC
Automating a specific instance of Visual Studio .NET using C#
关于c# - 我可以从我的外部 .dll 访问我的 c# 对象吗?也许使用 ROT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16287563/
我有一个小网站,我想在其中混淆一些文本,以保护不小心不及时阅读它的用户。 很像 imdb 上的关键词,你必须滚动才能显示它们。 我认为如果文本被标记,这将是一种很好的交互式方式来显示文本。 例子: H
目前,我正在编写一个程序,该程序使用 Java 对给定字符串执行 ROT-1 直到并包括 ROT-25。在我的研究之初,我发现this代码: public class Rot13 { public s
******************************************************************************* ROTS v1.05 Rem
我知道如何使用 *****.GetActiveObject(ProgId),但问题是我使用此代码行的几个应用程序没有添加到 ROT,即使它们已经打开,我得到HRESULT 错误。但是,如果我单击另一个
C++ 中字母的旋转 13 次换位未按我预期的方式工作。所有的字母首先都是大写的,所以只有 ASCII 数字 65-90 是相关的。如果字母超过 77,我会减去以回绕到“A”。 for (int j
我有这个方法可以测试我是否成功获得ROT: void func() { IRunningObjectTable *rot; qDebug() future = QtConcurren
基本上我必须使用 rot-13 将输入的字符数组转换为结果数组。所以,这就是我想做的事情:使用 for 循环,然后在 for 循环内使用条件来确定是否添加或减去 13 个位置。但我遇到的问题是编写 f
我知道有很多方法可以编写 ROT(n) 函数。但我不想有一些带有字符的表。 所以,我尝试编写一个带有解码器的简单 ROT(n),作为练习项目。编码功能工作正常。但解码器不断将“a”更改为“z”。 有人
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我需要获取正在运行的对象的特定实例(来自 C#)。可能有此应用程序的多个实例正在运行。不幸的是,此应用程序始终以完全相同的名称(例如,“!{DED89DB0-45B6-11CE-B307-080036
我已经对其进行了很多更改。而且,情况只会变得更糟。我不明白我做错了什么。从A-M,加13。从M-Z,减13。以前,至少我收到回信。现在,它们是符号。 import javax.swing.JOptio
我尝试实现 Rot13 并使其尽可能小,这是我目前的结果: if ( (c >= 'A') && (c = 'a') && (c = 'A') && (c = 'a') && (c = 'A'
我的代码多年来一直用于 PDF、HTML 文档和 XBRL 文档。从 IE 中的 BHO 或 Reader 中的 Adobe 插件调用代码。它在 ROT 中注册一个名字对象,并创建一个信号事件。
我想要一个函数,当传递一个只包含字母的字符串时,将字符串中的每个字母通过字母表旋转 X 个字符,其中 X 是函数的参数。著名的例子是当 X=13 时,称为 ROT-13 函数 <- ROTx(str,
我正在使用rot-js绘制带有六边形的网格,并希望将三 Angular 形和其他形状添加到 canvas 。我尝试过对 display.getContainer() 采取行动但这不起作用。需要做什么才
HZROT.cpp: #include "HZROT.h" std::string ROTEncode(std::string instring, int rot) { std::string
作为标准 Java 库之一的一部分,是否已经有 rot13() 和 unrot13() 实现?还是我必须自己编写并“重新发明轮子”? 它可能看起来像这样: int rot13 ( int c ) {
我正在尝试使用 R 对我的数据进行 PCA 分析,我发现 this nice guide , 使用 prcomp和 ggbiplot .我的数据是两种样本类型,每种类型具有三个生物学重复(即 6 行)
我有两个用 C++ 和 ATL 编写的 COM 对象。有一个图书馆,我知道他们的 IID 和 CLID。 我找不到在两个简单 COM 对象之间进行这种简单通信的示例。如何创建 IMoniker 以及如
我将网站上的所有电子邮件地址编码为 ROT-13,然后使用 Javascript 对地址进行解码(以避免垃圾邮件)。然而,在 IE 7 或 8 中,解码完全不起作用。在 Chrome、Safari、F
我是一名优秀的程序员,十分优秀!