VS2005中的C#:设备项目能否同时针对完整框架和CF?

VS2005中的C#:设备项目能否同时针对完整框架和CF?,c#,visual-studio,visual-studio-2005,compact-framework,C#,Visual Studio,Visual Studio 2005,Compact Framework,我们正在VisualStudio2005下使用Compact框架开发设备。然而,我们也希望制作一个在PC上运行的软件模拟版本(最好通过构建配置进行选择) 然而,似乎.vsproj文件是特定于设备的;例如,仅仅通过更改目标无法使用完整的.NET framework 这有什么办法吗?我想我们可以在PC机上运行compact framework,但该项目仍然不能以ARM处理器为目标,或者我假设JIT编译器将为PC机生成不可用的代码?我认为唯一的方法是为同一个项目创建两个项目文件。一个是普通的CF应用程

我们正在VisualStudio2005下使用Compact框架开发设备。然而,我们也希望制作一个在PC上运行的软件模拟版本(最好通过构建配置进行选择)

然而,似乎.vsproj文件是特定于设备的;例如,仅仅通过更改目标无法使用完整的.NET framework


这有什么办法吗?我想我们可以在PC机上运行compact framework,但该项目仍然不能以ARM处理器为目标,或者我假设JIT编译器将为PC机生成不可用的代码?

我认为唯一的方法是为同一个项目创建两个项目文件。一个是普通的CF应用程序,另一个与普通的.Net应用程序一样工作。让项目文件同时以CF和full framework为目标是不受支持的操作。

您可以在常规Windows(可能)中运行Compact framework应用程序。然而,这有两个主要的潜在问题

首先,由于compact框架中缺少完整框架中的某些窗体和控件属性,因此应用程序在Windows中的行为会有点奇怪。例如,在完整框架中,表单具有StartPosition属性,该属性确定表单首次创建时在屏幕上的显示位置。此属性在compact framework中不存在(原因很明显),因此当您在常规Windows中运行CF应用程序时,表单会选择默认的StartPosition值
WindowsDefaultLocation
,这意味着设置表单的左属性和顶属性对其显示位置没有影响,所以表单会在任何地方弹出

其次,CF中的任何Windows API PInvoke调用都必须引用“coredll”,而完整框架中的相同调用引用“user32”、“winmm”等。解决此问题的一种方法是执行以下操作:

[DllImport("winmm.dll", EntryPoint="waveOutReset")]
private static extern int waveOutResetFULL(IntPtr hWaveIn);
[DllImport("coredll.dll", EntryPoint="waveOutReset")]
private static extern int waveOutResetCF(IntPtr hWaveIn);
public static int waveOutReset(IntPtr hWaveIn)
{
    if (Environment.OSVersion.Platform == PlatformID.WinCE)
    {
        return waveOutResetCF(hWaveIn);
    }
    else
    {
        return waveOutResetFULL(hWaveIn);
    }
}
还有其他方法可以做到这一点

关于第一组问题,一种解决方案是,当应用程序在常规窗口中运行时,通过反射设置compact框架中缺少的属性。我认为更好的替代方法是将UI的所有元素封装为UserControls,每个元素都托管在一个“主”UserControl上,根据需要创建和处理其他UserControl元素。然后,您可以在表单的单个实例上承载单个“主”用户控件


顺便说一句,我为一家大型造船厂编写了一个应用程序,它可以做到这一点(在Windows和Windows移动设备上运行),并且它仍然在使用中。事实上,当造船厂出于安全原因暂时停止使用移动设备时,该应用程序在两种环境中运行的能力实际上挽救了它的生命。

贾里德是正确的,你不能让Studio这样做(当然,如果没有大量的努力和非常脆弱的最终结果)。不过,除此之外,还有许多其他事情需要注意

首先,MSIL是独立于处理器的,所以它不会从这个角度“生成不可用的代码”。ARM IL与x86 IL(或MIPS或SH3)相同。事实上,CF程序集可以直接在完整的框架中使用,因为它们是这样的(反之亦然,因为CF并没有实现桌面上的所有操作码)

也就是说,CF应用程序不调用特定于设备的API是非常少见的,无论它是coredll.dll的p/Invoke还是特定于设备的程序集,如Microsoft.WindowsMobile.dll。在这些情况下,程序集将在运行时(找不到本机DLL)或加载时(找不到引用的程序集)之外运行


你可以(有时需要付出很大的努力)解决这些问题。这取决于你来决定是否值得去做。我的经验是,一般来说,情况并非如此。只使用emulator或运行CE的虚拟PC就省力多了。

我维护的一些开源代码中有一个相关问题;我有单独的项目文件,但为了减少维护,我使用一个手工制作的项目文件,该文件自动包含项目树中的所有*.cs文件:

<ItemGroup>
  <Compile Include="..\protobuf-net\**\*.cs" />
</ItemGroup>


这样,我就不必一直记着将文件添加到其他构建脚本中——尽管我确实需要对删除过时的文件(不仅仅是从项目中删除它们)保持虔诚的态度。

我们在我工作的地方这样做,而且(大部分)很好。如果您只是将其用于仿真,那么还可以处理GDI+吐出的一些粗糙边缘。您只需确定不兼容的点,并将它们推到某种平台接口中,以解决那些严重破坏事物的问题


正如MusicGenesis敏锐地指出的,其中一个主要领域将是你的p/Invokes。我还收集了一个非常不完整的紧凑框架/完整框架错误列表:

一个解决方法是不使用VS。一个很好的例子是软件Basic4PPC(请参阅)

它是一种VB.Net风格的编程语言(使用它编写的所有应用程序都需要在设备上安装紧凑的框架)。然而,关键是您只使用一个IDE,相同的源代码,但您可以编译应用程序以在桌面或设备上运行。有许多可用的用户库,对于某些任务,可能需要为桌面或设备使用特定的库


这个程序是用C语言编写的。它非常值得一看。

我从不同的方向解决了一个类似的问题:我有一个实用程序库,可以完整和紧凑地工作,所以我使用了多个项目,但只有一组源文件

完整的csproj具有源文件,而紧凑的csproj具有指向这些文件的链接。每当一个类调用一个不在compact中的方法时,我就把它作为一个部分类,并且所讨论的方法在*.pc.cs和*.ppc.csf中实现