C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

スタートメニューに貼り付けてるリンクを保存したい

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■91130 / inTopicNo.1)  スタートメニューに貼り付けてるリンクを保存したい
  
□投稿者/ 裕次郎 (1回)-(2019/06/01(Sat) 11:00:13)

分類:[.NET 全般] 

Windows10を使っています。そのスタートメニューに貼り付けてる複数のwebのリンクを保存する方法を教えてください
引用返信 編集キー/
■91140 / inTopicNo.2)  Re[1]: スタートメニューに貼り付けてるリンクを保存したい
□投稿者/ 魔界の仮面弁士 (2190回)-(2019/06/03(Mon) 12:37:25)
No91130 (裕次郎 さん) に返信
> Windows10を使っています。そのスタートメニューに貼り付けてる複数のwebのリンクを保存する方法を教えてください

そこそこ面倒かも知れません。


=== 第一段階 ===

Windows 10 における【スタートメニュー】のフォルダーは、
 "Shell:Common Start Menu\"
 "Shell:Start Menu\"
の 2 箇所があります。まずはこの両方を System.IO.Directory.GetFiles 等で探索して、
Web のリンクを保持しているショートカットファイルを列挙します。
(既定では後者のパスに置かれますので、探索するのは後者のみだけでも良いかも知れません)

前者(%AllUsersProfile%\Microsoft\Windows\Start Menu\ ディレクトリ)は全ユーザー向けで、
Everyone および Users に対して読み取り専用なのに対し、
後者(%AppData%\Microsoft\Windows\Start Menu\ ディレクトリ)は自分専用で、
ログオンアカウントに対して読み書き可能という使い分けです。


なお、Web ページへのショートカットをスタートメニューに配置する場合、
そこに登録されるショートカットファイル形式と既定のパスは、
使用しているブラウザーによっても異なります。

‘Google Chrome’ における≪垂直三点リーダ→[その他のツール]→[ショートカットを作成]≫なら
Shell:Start Menu\Programs\Chrome アプリ\*.lnk

‘Microsoft Internet Explorer’ における≪歯車→[サイトをアプリビューに追加]≫の場合
Shell:Start Menu\*.website

―――というように。

--- 第一段階(補足)---

【スタートメニュー】ではなく【タイル】の方を探索したい場合、
標準的な方法を見つけられませんでした。
(Windows.UI.StartScreen 名前空間あたりで列挙できないのだろうか?)
どうやら本来は、プログラムから操作されるべきものではないとされているようです。
https://devblogs.microsoft.com/oldnewthing/?p=43743

ただし、PowerShell の Export-StartLayout スクリプトレットを用いて、
現在のタイル情報を XML データとして得ることはできるようです。
https://docs.microsoft.com/ja-jp/windows/configuration/customize-and-export-start-layout

*.lnk や *.webite や *.url ファイルなどをタイル表示している場合は、
上記の XML ファイルの DesktopApplicationLinkPath 属性から
ショートカットファイル名を調べられそうです。

また、Microsoft Edge でピン留めされた URL 情報の場合は、
その XML ファイルの AppUserModelID 属性が
"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge" な要素を探し、
その Arguments 属性を見ることで判断できそうです。


=== 第二段階 ===

スタートメニューまたはタイルからショートカットファイル名を発見したら
その内容を、下記の COM インターフェイスを通じて読み取ります。

*.lnk ファイルの場合:
{000214F9-0000-0000-C000-000000000046} IShellLinkW インターフェイス
https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nf-shobjidl_core-ishelllinkw-getpath
https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nf-shobjidl_core-ishelllinkw-getarguments
https://smdn.jp/programming/tips/createlnk/


*.url ファイル / *.website ファイルの場合:
{CABB0DA0-DA57-11CF-9974-0020AFD79762} IUniformResourceLocatorW インターフェイス
https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/dd565674%28v%3dvs.85%29
http://bbs.wankuma.com/index.cgi?mode=red&namber=42060&KLOG=72
引用返信 編集キー/
■91143 / inTopicNo.3)  Re[2]: スタートメニューに貼り付けてるリンクを保存したい
□投稿者/ 魔界の仮面弁士 (2191回)-(2019/06/03(Mon) 15:56:54)
No91140 (魔界の仮面弁士) に追記
>>Windows10を使っています。そのスタートメニューに貼り付けてる複数のwebのリンクを保存する方法を教えてください
> そこそこ面倒かも知れません。

とりあえず *.url と *.website 形式のみ列挙するサンプル。(*.lnk は面倒なので省略)
言語指定が無かったので、とりあえず Visual Basic で記述しています。

Option Strict On
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes
Imports System.Text

Module Module1
    Sub Main()
        Dim links As New List(Of String)()
        Dim targetDirs As String() = {"%AppData%\Microsoft\Windows\Start Menu\", "%AllUsersProfile%\Microsoft\Windows\Start Menu\"}

        For Each d In targetDirs.Select(AddressOf Environment.ExpandEnvironmentVariables)
            Dim q As IEnumerable(Of String) = Enumerable.Empty(Of String)()
            q = q.Concat(EnumerateAllFiles(d, "*.url"))
            q = q.Concat(EnumerateAllFiles(d, "*.website"))
            For Each lnk In q
                Console.WriteLine("[" & Path.GetFileNameWithoutExtension(lnk) & "]")
                Console.WriteLine(GetUrl(lnk))
                Console.WriteLine()
            Next
        Next
    End Sub

    Iterator Function EnumerateAllFiles(path As String, searchPattern As String) As IEnumerable(Of String)
        Try
            For Each s In Directory.EnumerateFiles(path, searchPattern, SearchOption.TopDirectoryOnly)
                Yield s
            Next
        Catch
        End Try
        Try
            For Each d In Directory.EnumerateDirectories(path)
                For Each s In EnumerateAllFiles(d, searchPattern)
                    Yield s
                Next
            Next
        Catch
        End Try
    End Function

    Private Function GetUrl(ByVal filePath As String) As String
        Dim urlFile As Object = Nothing
        Dim pFile As IPersistFile
        Dim locator As IUniformResourceLocatorW
        Try
            urlFile = CreateObject("InternetShortcut")
            pFile = DirectCast(urlFile, IPersistFile)
            pFile.Load(filePath, 0)
            locator = DirectCast(urlFile, IUniformResourceLocatorW)
            Dim url As String = String.Empty
            locator.GetUrl(url)
            Return url
        Finally
            Marshal.ReleaseComObject(urlFile)
        End Try
    End Function

    <ComImport(), Guid("CABB0DA0-DA57-11CF-9974-0020AFD79762")>
    <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    Private Interface IUniformResourceLocatorW
        Sub SetUrl(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pcszURL As String, ByVal dwInFlags As Integer)
        Sub GetUrl(<Out(), MarshalAs(UnmanagedType.LPWStr)> ByRef ppszURL As String)
        Sub InvokeCommand(ByVal purlici As IntPtr)
    End Interface
End Module

引用返信 編集キー/
■91150 / inTopicNo.4)  Re[3]: スタートメニューに貼り付けてるリンクを保存したい
□投稿者/ 裕次郎 (2回)-(2019/06/03(Mon) 21:12:43)

No91143 (魔界の仮面弁士 さん) に
返信

本当に素晴らしい御教授ありがとうございます。
レベルの高さに心より感服します心より感服します。
貴重な情報として参考しながらやってみます。
ありがとうございました!



> ■No91140 (魔界の仮面弁士) に追記
> >>Windows10を使っています。そのスタートメニューに貼り付けてる複数のwebのリンクを保存する方法を教えてください
>>そこそこ面倒かも知れません。
>
> とりあえず *.url と *.website 形式のみ列挙するサンプル。(*.lnk は面倒なので省略)
> 言語指定が無かったので、とりあえず Visual Basic で記述しています。
>
> Option Strict On
> Imports System
> Imports System.IO
> Imports System.Runtime.InteropServices
> Imports System.Runtime.InteropServices.ComTypes
> Imports System.Text
>
> Module Module1
> Sub Main()
> Dim links As New List(Of String)()
> Dim targetDirs As String() = {"%AppData%\Microsoft\Windows\Start Menu\", "%AllUsersProfile%\Microsoft\Windows\Start Menu\"}
>
> For Each d In targetDirs.Select(AddressOf Environment.ExpandEnvironmentVariables)
> Dim q As IEnumerable(Of String) = Enumerable.Empty(Of String)()
> q = q.Concat(EnumerateAllFiles(d, "*.url"))
> q = q.Concat(EnumerateAllFiles(d, "*.website"))
> For Each lnk In q
> Console.WriteLine("[" & Path.GetFileNameWithoutExtension(lnk) & "]")
> Console.WriteLine(GetUrl(lnk))
> Console.WriteLine()
> Next
> Next
> End Sub
>
> Iterator Function EnumerateAllFiles(path As String, searchPattern As String) As IEnumerable(Of String)
> Try
> For Each s In Directory.EnumerateFiles(path, searchPattern, SearchOption.TopDirectoryOnly)
> Yield s
> Next
> Catch
> End Try
> Try
> For Each d In Directory.EnumerateDirectories(path)
> For Each s In EnumerateAllFiles(d, searchPattern)
> Yield s
> Next
> Next
> Catch
> End Try
> End Function
>
> Private Function GetUrl(ByVal filePath As String) As String
> Dim urlFile As Object = Nothing
> Dim pFile As IPersistFile
> Dim locator As IUniformResourceLocatorW
> Try
> urlFile = CreateObject("InternetShortcut")
> pFile = DirectCast(urlFile, IPersistFile)
> pFile.Load(filePath, 0)
> locator = DirectCast(urlFile, IUniformResourceLocatorW)
> Dim url As String = String.Empty
> locator.GetUrl(url)
> Return url
> Finally
> Marshal.ReleaseComObject(urlFile)
> End Try
> End Function
>
> <ComImport(), Guid("CABB0DA0-DA57-11CF-9974-0020AFD79762")>
> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
> Private Interface IUniformResourceLocatorW
> Sub SetUrl(<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal pcszURL As String, ByVal dwInFlags As Integer)
> Sub GetUrl(<Out(), MarshalAs(UnmanagedType.LPWStr)> ByRef ppszURL As String)
> Sub InvokeCommand(ByVal purlici As IntPtr)
> End Interface
> End Module
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ