Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.ProjectReunion.InteractiveExperiences.TransportPackage" Version="$(MicrosoftProjectReunionInteractiveExperiencesTransportPackagePackageVersion)" />
<PackageVersion Include="Microsoft.FrameworkUDK" Version="$(MicrosoftFrameworkUDKVersion)" />
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="$(MicrosoftWindowsCsWinRTPackageVersion)" />
<PackageVersion Include="Microsoft.SourceLink.Common" Version="$(MicrosoftSourceLinkCommonVersion)" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="$(MicrosoftSourceLinkGitHubVersion)" />
<PackageVersion Include="Microsoft.Taef" Version="$(MicrosoftTaefVersion)" />
<PackageVersion Include="Microsoft.VisualStudio.SDK" Version="17.3.32804.24" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.2" />
<PackageVersion Include="NuGet.VisualStudio" Version="17.6.1" />
Expand All @@ -19,8 +21,11 @@
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="Microsoft.VSSDK.BuildTools" Version="17.4.2118" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="$(WindowsAppSDKVersion)" Condition=" '$(WindowsAppSDKVersion)' != '' " />
<!-- <PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.250720000-experimental" /> -->
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="$(MicrosoftWindowsAppSDKVersionPackageVersion)" />
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="$(CppWinRTVersion)" Condition=" '$(CppWinRTVersion)' != '' " />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="$(WindowsSDKBuildToolsVersion)" Condition=" '$(WindowsSDKBuildToolsVersion)' != '' " />
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="$(WILVersion)" Condition=" '$(WILVersion)' != '' " />
<PackageVersion Include="Taef.Managed" Version="$(MicrosoftTaefVersion)" />
</ItemGroup>
</Project>
</Project>
523 changes: 523 additions & 0 deletions WindowsAppRuntime.sln

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions build/AzurePipelinesTemplates/WindowsAppSDK-RunTests-Steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ steps:
filePath: tools\DevCheck\DevCheck.ps1
arguments: -NoInteractive -Offline -Verbose -CheckTestPfx -Clean -CheckDependencies -CheckVisualStudio -ShowSystemInfo
workingDirectory: '$(Build.SourcesDirectory)'
- task: UseDotNet@2
displayName: Use .NET 6 For TAEF test Runtime
inputs:
version: 6.0.428

- task: DownloadPipelineArtifact@2
displayName: 'Download Foundation'
Expand Down Expand Up @@ -164,6 +168,21 @@ steps:

- checkout: WindowsAppSDKConfig

- task: PowerShell@2
displayName: Set TAEF_CoreCLR env variable
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=TAEF_CoreCLR;isOutput=true]$(Agent.ToolsDirectory)\dotnet\shared\Microsoft.NETCore.App\6.0.36"
Write-Host "##vso[task.setvariable variable=TAEF_CoreCLR;]$(Agent.ToolsDirectory)\dotnet\shared\Microsoft.NETCore.App\6.0.36"

- task: PowerShell@2
displayName: Show TAEF_CoreCLR env variable
inputs:
targetType: 'inline'
script: |
Write-Host $env:TAEF_CoreCLR

- task: PowerShell@2
displayName: 'Run TAEF Tests'
inputs:
Expand Down
1 change: 0 additions & 1 deletion dev/Interop/StoragePickers/PickerLocalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,3 @@ namespace PickerLocalization {
return manager.MainResourceMap().GetValue(key).ValueAsString();
}
}

1 change: 0 additions & 1 deletion dev/Interop/StoragePickers/PickerLocalization.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@
namespace PickerLocalization {
winrt::hstring GetStoragePickersLocalizationText(winrt::hstring key);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!--<SelfContained>true</SelfContained>-->
<WindowsPackageType>None</WindowsPackageType>
<Platforms>x86;x64;ARM64</Platforms>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'x86'">win-x86</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'ARM64'">win-arm64</RuntimeIdentifier>
</PropertyGroup>

<PropertyGroup>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Taef" />
<PackageReference Include="Microsoft.WindowsAppSDK.Foundation" GeneratePathProperty="true" />
<PackageReference Include="Taef.Managed" />
<PackageReference Include="Microsoft.Windows.CsWinRT">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<None Update="StoragePickerComponentTests.testdef">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="taeftest.manifest">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<!--TAEF test for dotnet core runtime needs coreclr.dll-->
<!--<Target Name="CopyDotNet" AfterTargets="Build">
<ItemGroup>
<RuntimeFilesToCopy Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.AssetType)' == 'runtime' OR '%(ResolvedFileToPublish.AssetType)' == 'native'" />
</ItemGroup>

<Copy SourceFiles="@(RuntimeFilesToCopy)" DestinationFiles="@(RuntimeFilesToCopy->'$(OutDir)localDotNet\%(Filename)%(Extension)')" SkipUnchangedFiles="true"/>
</Target>-->

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Tests": [
{
"Description": "Storage Picker API",
"Filename": "StoragePickerComponentTests.dll",
"Parameters": "",
"Architectures": ["x64", "x86", "arm64"],
"Status": "Enabled"
}
]
}
153 changes: 153 additions & 0 deletions test/StoragePickerComponentTests/StoragePickersTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Windows.Storage.Pickers;
using WEX.Logging.Interop;
using WEX.TestExecution;
using WEX.TestExecution.Markup;

namespace StoragePickerComponentTests;

[TestClass]
public class StoragePickersTest
{
[AssemblyInitialize]
// This attribute is used by GenerateHelixWorkItems.ps1 to control how it creates the work items.
// The default is CreateWorkItemPerModule
//[TestProperty("HelixWorkItemCreation", "CreateWorkItemPerTestClass")]
//[TestProperty("CoreClrProfile", "net5")]
//[TestProperty("CoreClrProfile", "TestNetv8.0")]


//[TestProperty("RunAs", "UAP")]
//[TestProperty("UAP:AppxManifest", "StoragePickerTest-AppxManifest.xml")]
[TestProperty("IsolationLevel", "Class")]
[TestProperty("CoreClrProfile", "localDotnet")]
[TestProperty("ActivationContext", "taeftest.manifest")]
public static void AssemblyInitialize(TestContext testContext)
{
Log.Comment("AssemblyInitialize");
}

List<IntPtr> foundDialogs = new List<IntPtr>();
uint currentProcessId = 0;

// Win32 APIs for auto-closing dialogs
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
static extern bool CloseWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
static extern bool IsWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll", SetLastError = true)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
{
if (!IsWindow(hWnd))
{
return true;
}

// Get window's process ID
GetWindowThreadProcessId(hWnd, out uint processId);
if (processId != currentProcessId)
{
return true;
}

// Get window class name and title
StringBuilder className = new StringBuilder(256);
StringBuilder windowTitle = new StringBuilder(256);
GetClassName(hWnd, className, className.Capacity);
GetWindowText(hWnd, windowTitle, windowTitle.Capacity);

string classNameStr = className.ToString();
string titleStr = windowTitle.ToString();

// Look for common file picker dialog classes and titles
if (classNameStr.Contains("#32770") || // Common dialog class
classNameStr.Contains("FilePickerViewHost") ||
titleStr.Contains("Open") ||
titleStr.Contains("Save") ||
titleStr.Contains("Browse") ||
titleStr.Contains("Select"))
{
foundDialogs.Add(hWnd);
Console.WriteLine($"Found dialog: Class={classNameStr}, Title={titleStr}, HWND={hWnd}");
}

return true; // Continue enumeration
}

// Constants for Windows messages
const uint WM_CLOSE = 0x0010;
const uint WM_COMMAND = 0x0111;
const uint WM_KEYDOWN = 0x0100;
const uint VK_ESCAPE = 0x1B;

async Task CloseDialogsAfterDelay(int delayMs = 2000)
{
await Task.Delay(delayMs);

foundDialogs.Clear();
currentProcessId = (uint)Environment.ProcessId;

// Find all dialogs belonging to our process
EnumWindows(EnumWindowsCallback, IntPtr.Zero);

// Close found dialogs
foreach (var hWnd in foundDialogs)
{
if (IsWindow(hWnd))
{
Console.WriteLine($"Closing dialog with HWND: {hWnd}");

// Try multiple methods to close the dialog
// Method 1: Send WM_CLOSE message
PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);

// Method 2: Send Escape key (backup)
await Task.Delay(100);
if (IsWindow(hWnd))
{
PostMessage(hWnd, WM_KEYDOWN, new IntPtr(VK_ESCAPE), IntPtr.Zero);
}
}
}
}

[TestMethod]
public async Task SimpleAPlusBTest()
{
var picker = new FileOpenPicker(default);
Verify.AreEqual(2, 1 + 1);
var task = CloseDialogsAfterDelay(2500);
var file = await picker.PickSingleFileAsync();
await task;
// Trigger test failure for debugging
Verify.IsNotNull(file);
}
}
12 changes: 12 additions & 0 deletions test/StoragePickerComponentTests/taeftest.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

<file name="Microsoft.WindowsAppRuntime.dll">
<activatableClass
name="Microsoft.Windows.Storage.Pickers.FileOpenPicker"
threadingModel="both"
xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>

</assembly>
Loading